10 de outubro de 2007

Surpresas do SQL Server...

Hoje, no SQL Server 2005, executei duas queries (nomes de tabelas e campos modificados por motivos óbvios):

select name from schema.table where name = 'blah'

e

select name from schema.table where name = 'BLAH'

E para a minha surpresa ambas retornaram:

name
-------------
blah

1 Row(s) returned

Eu esperava que a segunda query retornasse ZERO linhas. Em DB2 esse seria o caso. Em Oracle esse seria o caso. Em Informix esse serie o caso. Em MySQL esse seria o caso. Acho - apesar de ter trabalhado muito pouco com ele - que até em Sybase esse seria o caso.

E mais, se há uma "unique constraint" definida sobre o campo em questão e tentarmos:

insert into schema.table (name) values ('BLAH')

A constraint previne o insert.

Nenhum outro banco de dados que eu conheça ignora a capitalização dos dados sendo selecionados ou inseridos.

A solução parece ser em usar uma "collation" diferente da default que não seja "case insensitive". O problema aí é como definir essa "collation". Só existem, pelo que entendi, três maneiras:

a) Modificar a "collation" default da instalação da instância
b) Modificar a "collation" default do banco em questão
c) Modificar a "collation" de cada coluna desejada

O problema de a) e b), na minha opinião e de acordo com os meus testes, é que a "collation" afeta também o nome dos objetos no banco. Portanto ao adotar uma "collation" que não ignore capitalização, veja o que acontece:

create table schema.table (name varchar(15)...);

SELECT * FROM schema.table;

SELECT * FROM SCHEMA.TABLE;

A primeira cláusula SELECT funciona corretamente. A segunda retorna com erro: não existe objeto SCHEMA.TABLE.

Exatamente: a capitalização seus comandos DML vão ter de obedecer a capitalização que você usou ao criar seus objetos com DDL. Se você criou "schema.table" (tudo em minúsculas) você terá de se referir ao objeto sempre em minúsculas...

Ai.

Ao que parece, a solução é definir a "collation" a nível de coluna - o que só parece afetar os dados residentes na coluna, ótimo.

Só que é um trabalho danado. Agora pra cada coluna que formos criar temos de pensar se ela pode ficar no modo default ("ignore case") ou se precisamos redefinir a "collation". Sem contar que como estamos migrando várias tabelas de DB2 pra SQL Server 2005, temos de olhar cada uma das tabelas sendo migradas e decidir o que fazer com cada uma das tabelas.

A não ser que eu tenha entendido mal alguma coisa...

Algum gênio de SQL Server por aí?

3 comentários:

Anônimo disse...

pelo que eu sei qndo vc instala o seu SQL SERVER vc define se ele é case sensitive ou não, pelo visto o seu SQL foi instalado como não case sensitive.

C.E. Lopes disse...

Anônimo, você não leu o post inteiro.

Se eu instalo o SQLServer como case sensitive, os objetos do banco passam a ser case sensitive também. O que não faz o menor sentido.

Indignado disse...

Se não me engano no mysql você também tem como definir isso, se vai ser sensitive ou não, e no ORacle IDEM...

Eu acho um absurdo ser insensitive. hahaha Masssss devo confessar que eu, como desenvolvedor, achava TSQL a forma mais fácil de trabalhar com banco...

Mas já tem uns 4 anos que não uso o SQLServer.

Abraços!