Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

CoqBlog

.NET is good :-)
{ Blog de coq }

Actualités

SQL Server et la gestion des espaces en fin de chaîne (ou 'test' = 'test ')

Il s'agit d'une petite chose qu'il vaut mieux garder en tête quand on développe sur/pour SQL Server, et probablement d'autres SGBD si j'en crois la raison avancée que nous verrons plus bas.
C'est particulièrement surprennant pour quelqu'un ayant l'habitude de travailler avec d'autres langages, comme C#, qui n'ont pas ce genre de comportement.

Les chaînes (typées varchar, nvarchar) contenant des espaces en fin de chaîne sont considérées égales à leurs équivalents ne les possédant pas, et ce sur pratiquement pour toutes les opérations reposant sur ou utilisant une comparaison à l'exception de la partie droite d'une clause LIKE.

 

Ainsi ce script affichera 'true' :

declare @Str nvarchar(256);
declare @StrLW nvarchar(256);

set @Str = N'test';
set @StrLW = N'test ';

select case when @Str = @StrLW
then N'true'
else N'false'
end

 

Celui-ci ne sortira qu'une entrée dans le jeu de résultats, et ce sera probablement la valeur de @Str :

create table test (txt nvarchar(256));
insert into test (txt) values (@Str);
insert into test (txt) values (@StrLW);
select distinct txt from test;

Celui-ci (identique au précédent si ce n'est l'inversion des ordres INSERT) sortira probablement la valeur de @StrLW :

create table test (txt nvarchar(256));
insert into test (txt) values (@StrLW);
insert into test (txt) values (@Str);
select distinct txt from test;

(Avec une vraie table et une requête plus poussée la valeur extraite dépendra probablement des indexes mis en oeuvre.)

 

La raison invoquée pour expliquer ce comportement pour le moins étrange est une compatibilité avec la norme SQL-92 : INF: How SQL Server Compares Strings with Trailing Spaces

SQL Server follows the ANSI/ISO SQL-92 specification (Section 8.2, <Comparison Predicate>, General rules #3) on how to compare strings with spaces. The ANSI standard requires padding for the character strings used in comparisons so that their lengths match before comparing them. The padding directly affects the semantics of WHERE and HAVING clause predicates and other Transact-SQL string comparisons. For example, Transact-SQL considers the strings 'abc' and 'abc ' to be equivalent for most comparison operations.
Source : INF: How SQL Server Compares Strings with Trailing Spaces

 

Concernant LIKE, je vous laisse exécuter les 2 scripts ci-dessous (les différences entre les 2 résident dans les types utilisés pour les variables et les chaînes littérales) et observer less résultats :

declare @Str nvarchar(256);
declare @StrLW nvarchar(256);

set @Str = N'test';
set @StrLW = N'test ';

select N'true' where @StrLW like @Str;
select N'true' where @Str like @StrLW;
select N'true' where @StrLW like N'test';
select N'true' where @Str like N'test ';

declare @Str varchar(256);
declare @StrLW varchar(256);

set @Str = 'test';
set @StrLW = 'test ';

select N'true' where @StrLW like @Str;
select N'true' where @Str like @StrLW;
select N'true' where @StrLW like 'test';
select N'true' where @Str like 'test ';

 

Ca peut ouvrir la voie à des casses-têtes plus ou moins graves...

Autant ce comportement ne me choque pas, et je dirais même que je m'y attendais, pour un type à largeur fixe (char, nchar) autant pour un type à longueur variable (varchar, nvarchar) je ne m'y attendais vraiment pas.

Donc essayons de retenir cette spécificité pour éviter de la redécouvrir dans la douleur la prochaine fois !

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: mardi 8 décembre 2009 23:58 par coq
Classé sous : ,

Commentaires

christian a dit :

Oui, çà vient de la norme ISO de SQL qui convient que les chaînes de caractères sont complétées par des espaces, c'est utilisé entre autres choses pour les comparaison. Ca n'est donc pas spécifique à SQL Server, bien au contraire.

L'ordre de résultat est réputé aléatoire dans ton exemple, car coup de bol le jeu de résultat est assez petit pour tenir dans une page, mais si il faut les placer dans 2 pages distinctes ou si comme tu le dis toi même il y a un index, etc. l'ordre du jeu de résultat n'est pas garantie !

Dans les bizzarerie du ou des moteurs de bases de données sur les chaînes de caractères, essaye aussi çà :

select case when 'aaaa' = 'AAAA' then 'true' else 'false' end

select case when 'aaaa' = 'àààà' then 'true' else 'false' end

En fonction du classement (COLLATE) courant les resultats peuvent être assez folklorique ;o)

# décembre 9, 2009 07:56

coq a dit :

Oui pour les collations je savais déjà qu'il était important de ne pas trop se louper sur leur choix :p

J'ai d'ailleurs eu quelques cas où pour être certains d'avoir une égalité parfaite je suis passé par une comparaison sur une conversion des chaînes en varbinary, par manque de confiance envers un COLLATE avec une collation BIN.

Quitte à choisir entre un éventuel problème de performance ou un éventuel bug louche...

Sur ces cas là l'aspect certitude était bien plus important que l'aspect performance (et le jeu de données était de toute façon relativement réduit).

# décembre 9, 2009 22:01
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01