Existe um equivalente T-SQL dos padrões [0-9]
e [a-z]
que me permitirá extrair valores de uma coluna que contém pontuação?
Por exemplo:
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]'
Isso retornaria valores em que os 3 primeiros caracteres são números entre 0 e 9 e o último caractere será uma letra entre a e z, portanto, retornaria coisas como 123a
e 456b
, mas não retornaria um valor de 12ABC
.
Quero saber se existe um equivalente para pontuação como [0-9]
é para números e [a-z]
é para letras para que retorne AB!23
e C?D789
?
Se eu pudesse usar uma expressão regular, poderia usar a expressão ^[a-zA-Z0-9]*$
para corresponder a caracteres alfanuméricos em uma string.
Where Value like '^[a-zA-Z0-9]*$'
Existe um equivalente SQL para isso?
Eu sei que esse tipo de coisa pode ser feito no RegEx, mas preciso disso no T-SQL, não consigo carregar nenhum assemblie personalizado neste servidor, portanto, não posso usar expressões regulares.
A coluna real é varchar(200) . A ordenação é Latin1_General_CI_AS. Estou usando o SQL Server 2012 Standard Edition.
A maior dificuldade em chegar a uma solução precisa está em definir exatamente quais caracteres serão incluídos (ou excluídos, conforme a direção que fizer mais sentido para a operação). Significado:
VARCHAR
dados / ASCII ou dadosNVARCHAR
/ Unicode? A lista de caracteres de pontuação para dados ASCII depende da página de código que, por sua vez, depende do agrupamento. ( nesta questão estamos lidando com dados ASCII ).Latin1_General_CI_AS
).
,,
,;
,:
, etc) ou significa caracteres não alfanuméricos?¢
,£
,¥
, etc?©
e™
?Â
,É
,Ñ
,ß
,Þ
estão incluídos?Æ
/æ
?Para ajudar a facilitar a clareza em relação ao comportamento esperado, a consulta a seguir mostrará todos os 256 caracteres do conjunto de caracteres Latin1 (ou seja, página de código 1252) e como funcionam as duas variações da solução proposta por @Shaneis . O primeiro campo (rotulado como
Latin1_General_CI_AS
) mostra aLIKE
cláusula conforme proposta por @Shaneis (no momento em que este livro foi escrito) e o segundo campo (rotulado comoLatin1_General_100_BIN2
) mostra uma modificação em que cancelei o Collation para especificar um binário (ou seja, um Collation terminando em_BIN2
; o_BIN
Os agrupamentos estão obsoletos, portanto, não os use se você tiver acesso às_BIN2
versões), o que significava que também precisava adicionar oA-Z
intervalo para filtrar letras maiúsculas, pois o agrupamento atual não diferencia maiúsculas de minúsculas:ATUALIZAR
Deve-se mencionar que SE alguém está realmente procurando encontrar caracteres que são classificados como "pontuação" (e não "símbolo de moeda", "símbolo matemático", etc) e SE não está proibido de usar SQLCLR / carregar um arquivo personalizado Assembly (o SQLCLR foi introduzido com o SQL Server 2005 e ainda não encontrei um bom motivo para não permitir isso, especialmente porque o Banco de Dados SQL V12 do Azure oferece suporte a
SAFE
Assemblies), então você pode usar Expressões Regulares, mas não pelo motivo que a maioria das pessoas iria adivinhar.Em vez de usar expressões regulares para criar um intervalo de caracteres mais funcional, ou mesmo em vez de usar algo como
\w
(significando qualquer caractere de "palavra"), você pode especificar a categoria Unicode dos caracteres que deseja filtrar e existem várias categorias definidas :https://www.regular-expressions.info/unicode.html#category
Você pode até especificar o Bloco Unicode para filtrar, como "InBengali" ou "InDingbats" ou "InOptical_Character_Recognition", etc:
https://www.regular-expressions.info/unicode.html#block
Existem vários exemplos de criação de funções RegEx para SQL Server (embora a maioria dos exemplos não siga as práticas recomendadas do SQLCLR), ou você pode baixar a versão gratuita da biblioteca SQL# (que eu criei) e usar a função escalar RegEx_IsMatch da seguinte maneira :
A
\p{P}
expressão significa\p
= Categoria Unicode e{P}
= todas as pontuações (em oposição a um tipo específico de pontuação, como "Pontuação do Conector"). E a categoria "Pontuação" inclui toda a pontuação em todos os idiomas! Você pode ver a lista completa no site Unicode.org através do seguinte link (existem atualmente 717 Code Points nessa categoria):http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AGeneral_Category%3DPunctuation%3A%5D
Uma versão atualizada da consulta de teste mostrada acima, incluindo outro campo que usa SQL#.RegEx_IsMatch com
\p{P}
, e os resultados de todos os 3 testes em todos os 256 caracteres da página de código 1252 (ou seja, Latin1_General) foram publicados em PasteBin.com em:Consulta T-SQL e resultados para filtrar tipos de caracteres
ATUALIZAÇÃO
O seguinte foi mencionado na discussão relacionada:
Nesse caso:
Existem 11 caracteres não ingleses incluídos no conjunto de caracteres Latin1/Página de código que não correspondem ao
a-z
intervalo. São eles:ð Ð Þ þ œ Œ š Š ž Ž Ÿ
. Eles precisam ser adicionados ao curinga e, embora não sejam necessários no momento, não faria mal nenhum adicioná-losA-Z
para que o padrão funcione tão bem em um agrupamento com distinção entre maiúsculas e minúsculas. O resultado final é:LIKE '%[^a-zA-Z0-9ðÐÞþœŒšŠžŽŸ]%'
Considerando que esses dados podem incluir "nomes de hotéis de todo o mundo", eu recomendo alterar o tipo de dados da coluna para
NVARCHAR
que você possa armazenar todos os caracteres de todos os idiomas. Manter isso comoVARCHAR
corre um risco muito alto de eventualmente ter perda de dados, pois você só pode representar os idiomas baseados em latim, e nem mesmo totalmente para aqueles que recebem as seis categorias suplementares de Unicode que fornecem caracteres adicionais relacionados ao latim.Posso estar simplificando demais isso um pouco, mas, se dissermos que a pontuação é tudo o que resta quando os valores alfanuméricos são removidos, o seguinte procurará por strings que contenham caracteres não alfanuméricos.