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 três 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, assim como [0-9]
para números e [a-z]
letras, para que retorne AB!23
e C?D789
?
Se eu pudesse usar uma expressão regular, poderia usá-la ^[a-zA-Z0-9]*$
para corresponder caracteres alfanuméricos em uma sequência.
Where Value like '^[a-zA-Z0-9]*$'
Existe um equivalente SQL para isso?
Conheço esse tipo de coisa que pode ser feito no RegEx, mas preciso no T-SQL, não consigo carregar nenhum assembly personalizado neste servidor, portanto não posso usar expressões regulares.
A coluna real é varchar (200) . O agrupamento é Latin1_General_CI_AS. Estou usando o SQL Server 2012 Standard Edition.
Respostas:
A maior dificuldade em chegar a uma solução precisa é definir exatamente quais caracteres devem ser incluídos (ou excluídos, qualquer que seja a direção que faça mais sentido para a operação). Significado:
VARCHAR
dados / ASCII ouNVARCHAR
/ dados 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™
?Â
,É
,Ñ
,ß
,Þ
incluído?Æ
/æ
?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 duas variações da solução proposta de @ Shaneis operam. O primeiro campo (rotulado como
Latin1_General_CI_AS
) mostra aLIKE
cláusula proposta por @Shaneis (no momento em que este artigo foi escrito) e o segundo campo (rotulado comoLatin1_General_100_BIN2
) mostra uma modificação na qual substituí o Collation para especificar um binário (ou seja, um Collation terminando em_BIN2
;_BIN
Os agrupamentos foram descontinuados, portanto, não os use se você tiver acesso às_BIN2
versões), o que significava que eu também precisava adicionar oA-Z
intervalo para filtrar as letras maiúsculas, pois o agrupamento atual não diferencia maiúsculas de minúsculas:ATUALIZAR
Deve-se mencionar que, se alguém estiver realmente procurando encontrar caracteres classificados como "pontuação" (e não "símbolo de moeda", "símbolo matemático" etc.), e se não for proibido usar o SQLCLR / carregar um costume Assembly (SQLCLR foi introduzido com o SQL Server 2005, e ainda preciso encontrar um bom motivo para não permitir, especialmente porque o Banco de Dados SQL do Azure V12 oferece suporte a
SAFE
Assemblies), então você pode usar Expressões Regulares, mas não pelo motivo que a maioria das pessoas adivinharia.Em vez de usar Expressões regulares para criar um intervalo de caracteres mais funcional, ou mesmo em vez de usar algo como
\w
(ou seja, qualquer caractere "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 inúmeros exemplos de criação de funções RegEx para SQL Server (embora a maioria dos exemplos não siga as práticas recomendadas de 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}
= toda pontuação (em oposição a um tipo específico de pontuação, como "Pontuação do Conector"). E a categoria "Pontuação" inclui todas as pontuações em todos os idiomas! Você pode ver a lista completa no site Unicode.org através do seguinte link (atualmente existem 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 mostrado acima, incluindo um outro campo que usa SQL # .RegEx_IsMatch com
\p{P}
, e os resultados de todos os 3 testes em todos os 256 caracteres de página de código 1252 (ou seja Latin1_General) foi postado no 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 que não estão em inglês que estão incluídos no conjunto de caracteres Latin1 / Página de códigos que não são correspondidos pelo
a-z
intervalo. Eles são:ð Ð Þ þ œ Œ š Š ž Ž Ÿ
. Eles precisam ser adicionados ao curinga e, embora não sejam necessários no momento, não faria mal adicionar,A-Z
para que o padrão funcione tão bem em um agrupamento que diferencia maiúsculas de minúsculas. O resultado final é:LIKE '%[^a-zA-Z0-9ðÐÞþœŒšŠžŽŸ]%'
Considerando-se que estes dados podem incluir "nomes de hotéis de todo o mundo", eu altamente recomendo mudar o tipo de dados da coluna a ser
NVARCHAR
de modo que você pode armazenar todos os caracteres de todas as línguas. 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 adicionais de Unicode que fornecem caracteres adicionais relacionados a latim.fonte
Posso simplificar um pouco demais isso, mas, se dissermos que a pontuação é o que resta quando os valores alfanuméricos são removidos, o seguinte procurará por seqüências de caracteres que contenham caracteres não alfanuméricos.
fonte