Saltar al contenido

¿Existe un equivalente de T-SQL para la puntuación como [0-9] es para números y [a-z] es para letras?

Solución:

La mayor dificultad para llegar a una solución precisa es definir exactamente qué caracteres deben incluirse (o excluirse, la 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 intercalación. (en esta Pregunta estamos tratando con datos ASCII).
  • ¿Estamos tratando con búsquedas que distinguen entre mayúsculas y minúsculas?
  • ¿En qué intercalación está configurada la columna? La intercalación nos indicará 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 “puntuación” para referirse solo a los caracteres de puntuación estándar (p. ej. ., ,, ;, :, 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 los símbolos como © y ?
  • ¿Qué caracteres se consideran “alfa”? Son caracteres no ingleses como Â, É, Ñ, ß, Þ ¿incluido?
  • Dado que esta Pregunta trata con teclados del Reino Unido (consulte la discusión de esta Pregunta), ¿qué pasa con el Æ / æ ¿personaje?

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 el LIKE cláusula propuesta por @Shaneis (al momento de escribir este artículo) y el segundo campo (etiquetado como Latin1_General_100_BIN2) muestra una modificación en la que anulé la clasificación para especificar uno binario (es decir, una clasificación que termina en _BIN2; los _BIN Las intercalaciones están en desuso, así que no las use si tiene acceso al _BIN2 versiones) lo que significaba que también necesitaba agregar en el A-Z range para filtrar las letras mayúsculas, ya que la clasificació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 realmente está buscando encontrar caracteres que se clasifiquen como “puntuación” (y no como “símbolo de moneda”, “símbolo matemático”, etc.), y SI uno no tiene prohibido usar SQLCLR / cargar un ensamblado personalizado (SQLCLR se introdujo con SQL Server 2005, y todavía no he encontrado un bien razón para no permitirlo, especialmente porque Azure SQL Database V12 admite SAFE Ensamblados), entonces puede usar expresiones regulares, pero no por la razón que la mayoría de la gente 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 por los 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

Hay 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 el escalar RegEx_IsMatch funcionan de la siguiente manera:

SQL#.RegEx_IsMatch(Unicode-String-Expression, N'p{P}', 1, NULL)

los p{P} medios de expresión p = Categoría Unicode y {P} = toda la puntuación (a diferencia de un tipo específico de puntuación, como “Puntuación del conector”). Y, la categoría “Puntuación” incluye toda la 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 han publicado en PasteBin.com en:

Consulta y resultados de T-SQL para filtrar tipos de caracteres


ACTUALIZAR

En la discusión relacionada se mencionó lo siguiente:

Ha 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 alfabéticos válidos.

En este caso:

  1. Hay 11 caracteres que no están en inglés que están incluidos en el juego de caracteres Latin1 / Página de códigos que no coinciden con el a-z distancia. Son: ð Ð Þ þ œ Œ š Š ž Ž Ÿ. Estos deben agregarse al comodín y, aunque no es necesario en este momento, no estaría de más agregar A-Z para que el patrón funcione igual de bien en una intercalación que distingue entre mayúsculas y minúsculas. El resultado final es:
    LIKE '%[^a-zA-Z0-9ðÐÞþœŒšŠžŽŸ]%'

  2. Teniendo en cuenta que estos datos pueden incluir “nombres de hoteles de todo el mundo”, muy recomiendo cambiar el tipo de datos de la columna para que sea NVARCHAR para que pueda almacenar todos los caracteres de todos los idiomas. Manteniendo esto como VARCHAR corre un riesgo muy alto de eventualmente tener pérdida de datos, ya que solo puede representar los idiomas basados ​​en latín, y ni siquiera completamente para aquellos dados las seis categorías Unicode suplementarias que proporcionan caracteres adicionales relacionados con el latín.

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, lo siguiente buscará cadenas que contengan caracteres no alfanuméricos.

Create Table #Test
(
Value   VarChar(10)
) 
Insert Into #Test
Values ('123a'), ('456b'), ('12ABC'),('AB!23'),('C?D789')

-- Original
Select      *
From        #Test
Where       Value like '[0-9][0-9][0-9][a-z]'

-- Non Alpha-numeric
SELECT * FROM #Test WHERE Value LIKE '%[^a-z0-9]%';

DROP TABLE #Test;
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *