¿Existe un equivalente T-SQL de los patrones [0-9]
y [a-z]
que me permita extraer valores de una columna que contiene puntuación?
Por ejemplo:
Create Table #Test
(
Value VarChar(10)
)
Insert Into #Test
Values ('123a'), ('456b'), ('12ABC'),('AB!23'),('C?D789')
Select *
From #Test
Where Value like '[0-9][0-9][0-9][a-z]'
Esto devolvería valores donde los primeros 3 caracteres son números entre 0 y 9 y el último carácter será una letra entre a y z, por lo que devolvería cosas como 123a
y 456b
pero no devolvería un valor de 12ABC
.
Quiero saber si hay un equivalente para la puntuación como lo [0-9]
es para los números y [a-z]
para las letras para que regrese AB!23
y C?D789
.
Si pudiera usar una expresión regular, podría usar la expresión ^[a-zA-Z0-9]*$
para unir caracteres alfanuméricos en una cadena.
Where Value like '^[a-zA-Z0-9]*$'
¿Hay un equivalente SQL para esto?
Sé este tipo de cosas que se pueden hacer en RegEx pero lo necesito en T-SQL, no puedo cargar ningún ensamblado personalizado en este servidor, así que no puedo usar expresiones regulares.
La columna real es varchar (200) . La clasificación es Latin1_General_CI_AS. Estoy usando SQL Server 2012 Standard Edition.
Respuestas:
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:
VARCHAR
datos / ASCII oNVARCHAR
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 ).Latin1_General_CI_AS
).
,,
,;
,:
, etc) o significa caracteres no alfanuméricos?¢
,£
,¥
, etc?©
y™
?Â
,É
,Ñ
,ß
,Þ
incluidos?Æ
/æ
?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 laLIKE
cláusula propuesta por @Shaneis (a partir de este escrito) y el segundo campo (etiquetado comoLatin1_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 elA-Z
rango para filtrar las letras mayúsculas, ya que la intercalación actual no distingue entre mayúsculas y minúsculas: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íaEn 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 :
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:
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 agregarlosA-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 comoVARCHAR
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.fuente
Puede que esté simplificando demasiado esto un poco, pero, si decimos que la puntuación es todo lo que queda cuando se eliminan los valores alfanuméricos, entonces lo siguiente buscará cadenas que tengan caracteres no alfanuméricos.
fuente