La mayor dificultad para llegar a una solución precisa es definir exactamente qué caracteres se incluirán (o excluirán, en cualquier dirección que tenga más sentido para la operación). Sentido:
- ¿Estamos hablando de
VARCHAR
datos / ASCII o NVARCHAR
datos Unicode? La lista de caracteres de puntuación para los datos ASCII depende de la página de códigos, que a su vez depende de la clasificación. ( en esta pregunta estamos tratando con datos ASCII ).
- ¿Estamos tratando con búsquedas sensibles a mayúsculas o minúsculas?
- ¿En qué clasificación está configurada la columna? La clasificación nos dirá tanto la página de códigos como la distinción entre mayúsculas y minúsculas. ( en esta pregunta estamos tratando
Latin1_General_CI_AS
)
- es el término "puntuacion" para significar sólo los caracteres de puntuación estándar (por ejemplo
.
, ,
, ;
, :
, etc) o significa caracteres no alfanuméricos?
- ¿Están incluidos los caracteres de espacio en blanco?
- ¿Están incluidos los personajes de control?
- ¿Qué pasa con los símbolos de moneda como
¢
, £
, ¥
, etc?
- ¿Qué pasa con símbolos como
©
y ™
?
- ¿Qué caracteres se consideran "alfa"? Se caracteres no ingleses como
Â
, É
, Ñ
, ß
, Þ
incluidos?
- Dado que esta pregunta trata sobre los teclados del Reino Unido (consulte la discusión de esta pregunta), ¿qué pasa con el carácter
Æ
/ æ
?
Para ayudar a facilitar la claridad con respecto al comportamiento esperado, la siguiente consulta mostrará los 256 caracteres del conjunto de caracteres Latin1 (es decir, la página de códigos 1252) y cómo funcionan dos variaciones de la solución propuesta de @ Shaneis . El primer campo (etiquetado como Latin1_General_CI_AS
) muestra la LIKE
cláusula propuesta por @Shaneis (a partir de este escrito) y el segundo campo (etiquetado como Latin1_General_100_BIN2
) muestra una modificación donde anulé la Clasificación para especificar una binaria (es decir, una Clasificación que termina en _BIN2
; el _BIN
Las intercalaciones están en desuso, así que no las use si tiene acceso a las _BIN2
versiones), lo que significa que también necesitaba agregar el A-Z
rango para filtrar las letras mayúsculas, ya que la intercalación actual no distingue entre mayúsculas y minúsculas:
;WITH nums AS
(
SELECT TOP (256) (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1) AS [Decimal]
FROM [master].[sys].[all_objects]
)
SELECT nm.[Decimal],
CHAR(nm.[Decimal]) AS [Character],
CASE WHEN CHAR(nm.[Decimal]) LIKE '%[^a-z0-9]%'
THEN 'x' ELSE '' END AS [Latin1_General_CI_AS],
CASE WHEN CHAR(nm.[Decimal]) LIKE '%[^a-z0-9A-Z]%' COLLATE Latin1_General_100_BIN2
THEN 'x' ELSE '' END AS [Latin1_General_100_BIN2]
FROM nums nm;
ACTUALIZAR
Cabe mencionar que SI uno está realmente tratando de encontrar personajes que se clasifican como "puntuacion" (y no "símbolo de la moneda", "símbolo matemático", etc), y SI no tiene prohibido utilizar SQLCLR / cargar una costumbre Ensamblaje (SQLCLR se introdujo con SQL Server 2005, y todavía no he encontrado una buena razón para no permitirlo, especialmente dado que Azure SQL Database V12 es compatible con SAFE
ensamblajes), entonces puede usar Expresiones regulares, pero no por la razón por la que la mayoría de las personas adivinaría
En lugar de usar Expresiones regulares para construir un rango de caracteres más funcional, o incluso en lugar de usar algo como \w
(es decir, cualquier carácter de "palabra"), puede especificar la Categoría Unicode de los caracteres que desea filtrar, y hay varias categorías definidas :
https://www.regular-expressions.info/unicode.html#category
Incluso puede especificar el bloque Unicode para filtrar, como "InBengali" o "InDingbats" o "InOptical_Character_Recognition", etc.
https://www.regular-expressions.info/unicode.html#block
Existen numerosos ejemplos de creación de funciones RegEx para SQL Server (aunque la mayoría de los ejemplos no siguen las mejores prácticas de SQLCLR), o puede descargar la versión gratuita de la biblioteca SQL # (que creé) y usar la función escalar RegEx_IsMatch de la siguiente manera :
SQL#.RegEx_IsMatch(Unicode-String-Expression, N'\p{P}', 1, NULL)
La \p{P}
expresión significa \p
= Categoría Unicode y {P}
= toda la puntuación (en oposición a un tipo específico de puntuación, como "Puntuación de conector"). Y, la categoría "Puntuación" incluye todos los signos de puntuación en todos los idiomas. Puede ver la lista completa en el sitio Unicode.org a través del siguiente enlace (actualmente hay 717 puntos de código en esa categoría):
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AGeneral_Category%3DPunctuation%3A%5D
Una versión actualizada de la consulta de prueba que se muestra arriba, incluido otro campo que usa SQL # .RegEx_IsMatch con \p{P}
, y los resultados de las 3 pruebas en los 256 caracteres de la página de códigos 1252 (es decir, Latin1_General) se ha publicado en PasteBin.com en:
Consulta T-SQL y resultados para filtrar tipos de caracteres
ACTUALIZACIÓN
Se mencionó lo siguiente en la discusión relacionada:
Has hecho un buen comentario sobre los caracteres acentuados, ya que son nombres de hoteles de todo el mundo habrá caracteres acentuados en los nombres, para mi problema, me gustaría clasificarlos como caracteres alfa válidos.
En este caso:
Hay 11 caracteres que no están en inglés que se incluyen en el conjunto de caracteres Latin1 / Página de códigos que no coinciden con el a-z
rango. Ellos son: ð Ð Þ þ œ Œ š Š ž Ž Ÿ
. Estos deben agregarse al comodín y, aunque no son necesarios en este momento, no estaría de más agregarlos A-Z
para que el patrón funcione igual de bien en una clasificación sensible a mayúsculas y minúsculas. El resultado final es:
LIKE '%[^a-zA-Z0-9ðÐÞþœŒšŠžŽŸ]%'
Teniendo en cuenta que estos datos pueden incluir "nombres de hoteles de todo el mundo", me altamente recomiendan cambiar el tipo de datos de la columna que se va NVARCHAR
para que pueda almacenar todos los caracteres de todos los idiomas. Mantener esto como VARCHAR
un riesgo muy alto de eventualmente tener pérdida de datos ya que solo puede representar los idiomas basados en el latín, y ni siquiera completamente para aquellos que reciben las seis categorías Unicode suplementarias que proporcionan caracteres adicionales relacionados con el latín.