AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 34730
Accepted
Iain Samuel McLean Elder
Iain Samuel McLean Elder
Asked: 2013-02-15 03:37:12 +0800 CST2013-02-15 03:37:12 +0800 CST 2013-02-15 03:37:12 +0800 CST

Por que os não-dígitos são LIKE [0-9]?

  • 772

O agrupamento padrão do meu servidor é Latin1_General_CI_AS, conforme determinado por esta consulta:

SELECT SERVERPROPERTY('Collation') AS Collation;

Fiquei surpreso ao descobrir que, com esse agrupamento, posso corresponder a caracteres não numéricos em strings usando o predicado LIKE '[0-9]'.

Por que no agrupamento padrão isso acontece? Não consigo pensar em um caso em que isso seria útil. Sei que posso contornar o comportamento usando um agrupamento binário, mas parece uma maneira estranha de implementar o agrupamento padrão.

A filtragem de dígitos produz caracteres não dígitos

Posso demonstrar o comportamento criando uma coluna que contém todos os valores possíveis de caractere de byte único e filtrando os valores com o predicado de correspondência de dígitos.

A instrução a seguir cria uma tabela temporária com 256 linhas, uma para cada ponto de código na página de código atual:

WITH P0(_) AS (SELECT 0 UNION ALL SELECT 0),
P1(_) AS (SELECT 0 FROM P0 AS L CROSS JOIN P0 AS R),
P2(_) AS (SELECT 0 FROM P1 AS L CROSS JOIN P1 AS R),
P3(_) AS (SELECT 0 FROM P2 AS L CROSS JOIN P2 AS R),
Tally(Number) AS (
  SELECT -1 + ROW_NUMBER() OVER (ORDER BY (SELECT 0))
  FROM P3
)
SELECT Number AS CodePoint, CHAR(Number) AS Symbol
INTO #CodePage
FROM Tally
WHERE Number >= 0 AND Number <= 255;

Cada linha contém o valor inteiro do ponto de código e o valor do caractere do ponto de código. Nem todos os valores de caracteres podem ser exibidos - alguns dos pontos de código são estritamente caracteres de controle. Aqui está uma amostra seletiva da saída de SELECT CodePoint, Symbol FROM #CodePage:

0   
1   
2   
...
32   
33  !
34  "
35  #
...
48  0
49  1
50  2
...
65  A
66  B
67  C
...
253 ý
254 þ
255 ÿ

Eu esperaria ser capaz de filtrar a coluna Symbol para encontrar caracteres de dígitos usando um predicado LIKE e especificando o intervalo de caracteres '0' a '9':

SELECT CodePoint, Symbol
FROM #CodePage
WHERE Symbol LIKE '[0-9]';

Produz uma saída surpreendente:

CodePoint   Symbol
48  0
49  1
50  2
51  3
52  4
53  5
54  6
55  7
56  8
57  9
178 ²
179 ³
185 ¹
188 ¼
189 ½
190 ¾

O conjunto de pontos de código 48 a 57 é o que eu espero. O que me surpreende é que os símbolos para sobrescritos e frações também estão incluídos no conjunto de resultados!

Pode haver uma razão matemática para pensar em expoentes e frações como números, mas parece errado chamá-los de dígitos.

Usando o agrupamento binário como uma solução alternativa

Entendo que, para obter o resultado esperado, posso forçar o agrupamento binário correspondente Latin1_General_BIN:

SELECT CodePoint, Symbol
FROM #CodePage
WHERE Symbol LIKE '[0-9]' COLLATE Latin1_General_BIN;

O conjunto de resultados inclui apenas os pontos de código 48 a 57:

CodePoint   Symbol
48  0
49  1
50  2
51  3
52  4
53  5
54  6
55  7
56  8
57  9
sql-server collation
  • 2 2 respostas
  • 19696 Views

2 respostas

  • Voted
  1. Best Answer
    Martin Smith
    2013-02-15T03:46:34+08:002013-02-15T03:46:34+08:00

    [0-9]não é algum tipo de expressão regular definida apenas para corresponder a dígitos.

    Qualquer intervalo em um LIKEpadrão corresponde aos caracteres entre o caractere inicial e final de acordo com a ordem de classificação do agrupamento.

    SELECT CodePoint,
           Symbol,
           RANK() OVER (ORDER BY Symbol COLLATE Latin1_General_CI_AS) AS Rnk
    FROM   #CodePage
    WHERE  Symbol LIKE '[0-9]' COLLATE Latin1_General_CI_AS
    ORDER  BY Symbol COLLATE Latin1_General_CI_AS 
    

    devoluções

    CodePoint            Symbol Rnk
    -------------------- ------ --------------------
    48                   0      1
    188                  ¼      2
    189                  ½      3
    190                  ¾      4
    185                  ¹      5
    49                   1      5
    50                   2      7
    178                  ²      7
    179                  ³      9
    51                   3      9
    52                   4      11
    53                   5      12
    54                   6      13
    55                   7      14
    56                   8      15
    57                   9      16
    

    Portanto, você obtém esses resultados porque, em seu agrupamento padrão, esses caracteres são classificados depois, 0mas antes 9.

    Parece que o agrupamento é definido para realmente classificá-los em ordem matemática com as frações na ordem correta entre 0e 1.

    Você também pode usar um conjunto em vez de um intervalo. Para evitar a 2correspondência ², você precisaria de um CSagrupamento

    SELECT CodePoint, Symbol
    FROM #CodePage
    WHERE Symbol LIKE '[0123456789]' COLLATE Latin1_General_CS_AS
    
    • 23
  2. Remus Rusanu
    2013-02-15T04:01:49+08:002013-02-15T04:01:49+08:00

    Latin1 é a página de código 1252, na qual 178 é 'SUPERSCRIPT TWO' . Este é um sobrescrito Unicode : é o caractere "2" como sobrescrito . De acordo com o Padrão Técnico Unicode nº 10 , deve ser comparado igual a 2, consulte 8.1 Collation Folding :

    Equivalentes de compatibilidade de mapa (terciários), como largura total e caracteres sobrescritos , para caracteres representativos

    O bug seria se o sobrescrito 2 fosse comparado diferente de 2! Antes de dizer 'mas minha coluna não é Unicode', fique tranquilo: de acordo com o MSDN (consulte Windows Collations), todas as comparações e classificações de strings são feitas de acordo com as regras do Unicode, mesmo quando a representação no disco é CHAR.

    Quanto aos outros caracteres do seu exemplo, like VULGAR FRACTION ONE QUARTERe like eles não comparam igual a nenhum número, mas, como Mark já mostrou, eles classificam corretamente entre 0 e 9.

    E, é claro, se você alterasse a página de código, obteria resultados diferentes. Por exemplo. com Greek_CS_AS( página de código 1253 ) você obteria os caracteres com o código 178, 179 e 189.

    • 6

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Conceder acesso a todas as tabelas para um usuário

    • 5 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve