O operador LIKE diferencia maiúsculas de minúsculas no MSSQL Server?

99

Na documentação sobre o operador LIKE , nada é dito sobre a distinção entre maiúsculas e minúsculas dele. É isso? Como habilitar / desabilitar?

Estou consultando varchar(n)colunas, em uma instalação do Microsoft SQL Server 2005, se isso importa.

Marcel
fonte
14
Depende do agrupamento de sua coluna (ou banco de dados). Se LIKELIKE
diferencia
Verifique a documentação sobre agrupamentos do SQL-Server msdn.microsoft.com/en-us/library/ms144250%28v=sql.105%29.aspx
GarethD
Qual é o teu objetivo? Você quer que seja sensível a maiúsculas ou não?
Aaron Bertrand
1
A distinção entre maiúsculas e minúsculas é padronizada para o agrupamento na coluna, cujo padrão é aquele no banco de dados. A maioria das vezes é arredondada, qual caminho você quer seguir?
Tony Hopkinson

Respostas:

101

Não é o operador que diferencia maiúsculas de minúsculas, é a própria coluna.

Quando uma instalação do SQL Server é executada, um agrupamento padrão é escolhido para a instância. A menos que seja explicitamente mencionado de outra forma (verifique a cláusula de agrupamento abaixo) quando um novo banco de dados é criado, ele herda o agrupamento da instância e quando uma nova coluna é criada, ela herda o agrupamento do banco de dados ao qual pertence.

Um agrupamento como sql_latin1_general_cp1_ci_asdita como o conteúdo da coluna deve ser tratado. CI significa sensível a maiúsculas e minúsculas e AS significa sensível a acentos.

Uma lista completa de agrupamentos está disponível em https://msdn.microsoft.com/en-us/library/ms144250(v=sql.105).aspx

(a) Para verificar um agrupamento de instância

select serverproperty('collation')

(b) Para verificar um agrupamento de banco de dados

select databasepropertyex('databasename', 'collation') sqlcollation

(c) Para criar um banco de dados usando um agrupamento diferente

create database exampledatabase
collate sql_latin1_general_cp1_cs_as 

(d) Para criar uma coluna usando um agrupamento diferente

create table exampletable (
    examplecolumn varchar(10) collate sql_latin1_general_cp1_ci_as null
)

(e) Para modificar um agrupamento de coluna

alter table exampletable
alter column examplecolumn varchar(10) collate sql_latin1_general_cp1_ci_as null

É possível alterar uma instância e agrupamentos de banco de dados, mas isso não afeta os objetos criados anteriormente.

Também é possível alterar um agrupamento de coluna em tempo real para comparação de strings, mas isso é altamente não recomendado em um ambiente de produção porque é extremamente caro.

select
  column1 collate sql_latin1_general_cp1_ci_as as column1
from table1
lolol
fonte
5
Parece que a gama de caracteres como [A-Z]sempre não faz distinção entre maiúsculas e minúsculas. [ABCDEFGHIJKLMNOPQRSŠTUVWXYZŽÅÄÖ]no entanto, parece obedecer ao agrupamento.
jumxozizi
1
Além disso, você pode consultar a diferenciação de maiúsculas e minúsculas de uma coluna específica com algo assim:select COLLATION_NAME, iif(cast(COLLATIONPROPERTY(COLLATION_NAME, 'ComparisonStyle') as int) & 1 = 0, 'case sensitive', 'case insensitive') from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'exampletable' and COLUMN_NAME = 'examplecolumn'
Jeppe Stig Nielsen
@jumxozizi Eu adicionei sua sugestão à resposta.
John Zabroski
@JeppeStigNielsen Eu adicionei sua sugestão à resposta.
John Zabroski
18

Toda essa conversa sobre agrupamento parece um pouco complicada demais. Por que não usar algo como:

IF UPPER(@@VERSION) NOT LIKE '%AZURE%'

Então, seu cheque não diferencia maiúsculas de minúsculas, seja qual for o agrupamento

Phil R
fonte
10
Porque isso não é sargável. Seu exemplo usa uma variável e um curinga inicial. Mas contra uma coluna indexada com um agrupamento sem distinção entre maiúsculas e minúsculas like 'a%'poderia usar o índice e a upperversão não.
Martin Smith
3
A questão era se o likeoperador diferencia maiúsculas de minúsculas ou não .
jumxozizi
Você precisa saber o agrupamento, caso contrário, fazer isso pode ser inútil. Por exemplo, se a coluna que está sendo consultada usa Latin1_General_CI_AS, então fazer UPPER(@@VALUE) NOT LIKE '%SOMETHING%'ou @@COLUMN NOT LIKE '%SOMETHING%'é irrelevante: o resultado seria o mesmo.
rsenna
13

Você tem a opção de definir a ordem de agrupamento no momento de definir sua tabela. Se você definir um pedido com distinção entre maiúsculas e minúsculas, sua LIKEoperadora se comportará de maneira sensível; se você definir uma ordem de agrupamento que não diferencia maiúsculas de minúsculas, o LIKEoperador também ignorará as maiúsculas e minúsculas:

CREATE TABLE Test (
    CI_Str VARCHAR(15) COLLATE Latin1_General_CI_AS -- Case-insensitive
,   CS_Str VARCHAR(15) COLLATE Latin1_General_CS_AS -- Case-sensitive
);

Aqui está uma demonstração rápida no sqlfiddle mostrando os resultados da ordem de agrupamento nas pesquisas com LIKE.

dasblinkenlight
fonte
12

Se você deseja realizar uma pesquisa com distinção entre maiúsculas e minúsculas sem alterar o agrupamento da coluna / banco de dados / servidor, você sempre pode usar a COLLATEcláusula, por exemplo

USE tempdb;
GO
CREATE TABLE dbo.foo(bar VARCHAR(32) COLLATE Latin1_General_CS_AS);
GO
INSERT dbo.foo VALUES('John'),('john');
GO
SELECT bar FROM dbo.foo 
  WHERE bar LIKE 'j%';
-- 1 row

SELECT bar FROM dbo.foo 
  WHERE bar COLLATE Latin1_General_CI_AS LIKE 'j%';
-- 2 rows

GO    
DROP TABLE dbo.foo;

Funciona de outra maneira também, se sua coluna / banco de dados / servidor diferencia maiúsculas de minúsculas e você não deseja uma pesquisa com diferenciação de maiúsculas e minúsculas, por exemplo

USE tempdb;
GO
CREATE TABLE dbo.foo(bar VARCHAR(32) COLLATE Latin1_General_CI_AS);
GO
INSERT dbo.foo VALUES('John'),('john');
GO
SELECT bar FROM dbo.foo 
  WHERE bar LIKE 'j%';
-- 2 rows

SELECT bar FROM dbo.foo 
  WHERE bar COLLATE Latin1_General_CS_AS LIKE 'j%';
-- 1 row

GO
DROP TABLE dbo.foo;
Aaron Bertrand
fonte
Cuidado na última consulta, se você usá- WHERE bar COLLATE Latin1_General_CS_AS LIKE '[j-k]%'lo retornará Johncomo neste agrupamento a maiúscula Jestá entre minúsculas je minúsculas k. É assim aAbBcC...jJkKlLmM...que não é óbvio. Parece Latin1_General_BINmais previsível com buscas por intervalo com operador LIKE.
semana
7

O likeoperador usa duas strings. Essas strings devem ter agrupamentos compatíveis, o que é explicado aqui .

Na minha opinião, as coisas ficam complicadas. A consulta a seguir retorna um erro dizendo que os agrupamentos são incompatíveis:

select *
from INFORMATION_SCHEMA.TABLES
where 'abc' COLLATE SQL_Latin1_General_CP1_CI_AS like 'ABC' COLLATE SQL_Latin1_General_CP1_CS_AS

Em uma máquina aleatória aqui, o agrupamento padrão é SQL_Latin1_General_CP1_CI_AS. A consulta a seguir é bem-sucedida, mas não retorna nenhuma linha:

select *
from INFORMATION_SCHEMA.TABLES
where 'abc' like 'ABC' COLLATE SQL_Latin1_General_CP1_CS_AS

Os valores "abc" e "ABC" não correspondem em um mundo com distinção entre maiúsculas e minúsculas.

Em outras palavras, há uma diferença entre não ter agrupamento e usar o agrupamento padrão. Quando um lado não tem agrupamento, é "atribuído" um agrupamento explícito do outro lado.

(Os resultados são os mesmos quando o agrupamento explícito está à esquerda.)

Gordon Linoff
fonte
Você pode reproduzir o erro em uma tabela que NÃO é um objeto do sistema, como INFORMATION_SCHEMA.TABLES?
Aaron Bertrand
@AaronBertrand. . . Sim eu posso. O banco de dados está quebrado;)?
Gordon Linoff
Não sei, estou em um dispositivo móvel agora e não consigo ativar uma VM do Windows. Só não sei se toda a sua descrição é tecnicamente precisa.
Aaron Bertrand
4

Tente correr,

SELECT SERVERPROPERTY('COLLATION')

Em seguida, descubra se o agrupamento diferencia maiúsculas de minúsculas ou não.

RandomUs1r
fonte
1

Você pode alterar a propriedade de cada item.

maiúsculas e Minúsculas

Daniel Cadena
fonte
0

Você pode alterar facilmente o agrupamento no Microsoft SQL Server Management Studio.

  • clique com o botão direito na tabela -> design.
  • escolha sua coluna, role para baixo as propriedades da coluna até Collation.
  • Defina sua preferência de classificação marcando "Diferenciar maiúsculas de minúsculas"
Anders Finn Jørgensen
fonte