135 votes

La fonction LEN n'inclut pas les espaces de fin de ligne dans SQL Server

J'ai la table de test suivante dans SQL Server 2005 :

CREATE TABLE [dbo].[TestTable]
(
 [ID] [int] NOT NULL,
 [TestField] [varchar](100) NOT NULL
) 

Peuplé de :

INSERT INTO TestTable (ID, TestField) VALUES (1, 'A value');   -- Len = 7
INSERT INTO TestTable (ID, TestField) VALUES (2, 'Another value      '); -- Len = 13 + 6 spaces

Lorsque j'essaie de trouver la longueur de TestField avec la fonction LEN() de SQL Server, elle ne compte pas les espaces de fin de ligne - par exemple :

-- Note: Also results the grid view of TestField do not show trailing spaces (SQL Server 2005).
SELECT 
 ID, 
 TestField, 
 LEN(TestField) As LenOfTestField, -- Does not include trailing spaces
FROM 
 TestTable

Comment inclure les espaces de fin de ligne dans le résultat de la longueur ?

4 votes

Je pense que la vraie solution ici serait que Microsoft répare son logiciel défectueux. Votez ici : feedback.azure.com/forums/908035-sql-server/suggestions/

149voto

Jason Snelders Points 1586

Ceci est clairement documenté par Microsoft dans MSDN à l'adresse suivante http://msdn.microsoft.com/en-us/library/ms190329(SQL.90).aspx qui stipule que LEN "renvoie le nombre de caractères de l'expression de chaîne de caractères spécifiée, à l'exclusion des blancs de fin de chaîne". Il s'agit toutefois d'un détail facile à manquer si vous n'êtes pas vigilant.

Vous devez plutôt utiliser la fonction DATALENGTH - cf. http://msdn.microsoft.com/en-us/library/ms173486(SQL.90).aspx - qui "renvoie le nombre d'octets utilisés pour représenter une expression quelconque".

Exemple :

SELECT 
    ID, 
    TestField, 
    LEN(TestField) As LenOfTestField,           -- Does not include trailing spaces
    DATALENGTH(TestField) As DataLengthOfTestField      -- Shows the true length of data, including trailing spaces.
FROM 
    TestTable

57 votes

NOTE : Pour DATALENGTH vous devrez également diviser le résultat par 2 si l'expression testée est un type de caractère large (Unicode ; nchar, nvarchar ou ntext), puisque le résultat est en format octets pas caractères .

0 votes

Excellent point @devstuff et un autre piège potentiel pour les imprudents.

8 votes

Aussi pour varchar etc. Cela peut dépendre de la collation et même une simple division par 2 n'est pas fiable. Voir exemple ici

105voto

Serge Points 2386

Vous pouvez utiliser cette astuce :

LEN(Str + 'x') - 1

17 votes

Pourriez-vous nous éclairer sur les meilleures alternatives, s'il vous plaît ? Datalength ne l'est certainement pas.

0 votes

La réponse du haut semble raisonnable. Pour les chaînes Unicode, vous devez probablement diviser par 2. L2S et EF procèdent de cette manière.

19 votes

Je ne suis pas du tout d'accord pour dire que l'utilisation d'une méthode incohérente (dans certains cas, vous divisez le résultat par 2 et dans d'autres non) est une meilleure option. Peut-être que ma méthode a un impact sur les performances proche de zéro.

16voto

crokusek Points 448

"Comment inclure les espaces de fin de ligne dans le résultat de la longueur ?"

Vous demandez à quelqu'un de déposer une demande d'amélioration/un rapport de bug pour SQL Server car presque toutes les solutions de contournement répertoriées pour ce problème étonnamment simple présentent des lacunes ou sont inefficaces. Cela semble toujours être le cas dans SQL Server 2012. La fonction de découpage automatique peut provenir de la norme ANSI/ISO SQL-92, mais il semble qu'il y ait quelques trous (ou l'absence de comptage de ceux-ci).

Veuillez voter pour "Ajouter un paramètre pour que LEN compte les espaces blancs de fin de ligne" ici :

https://feedback.azure.com/forums/908035-sql-server/suggestions/34673914-add-setting-so-len-counts-trailing-whitespace

Lien Connecté à la retraite : https://connect.microsoft.com/SQLServer/feedback/details/801381

2 votes

El datalength La solution est encore pire à partir du serveur SQL 2012, car il prend désormais en charge les paires de substituts en UTF-16, ce qui signifie qu'un caractère peut utiliser jusqu'à 4 octets. Il est vraiment temps qu'ils corrigent le len pour se conformer à l'ANSI, ou au moins fournir une fonction dédiée pour compter les caractères incluant les espaces de fin.

1 votes

Le lien de rétroaction doit être utilisé davantage à cette fin. Il est déconcertant que ce problème ne puisse être recherché que via internet. J'ai passé près de 2 heures à essayer de trouver où j'avais fait une erreur dans mon propre code avant même de considérer que la fonction LEN() était la cause de ma déconnexion.

0 votes

Je suis d'accord avec cela, mais je devrais autoriser un paramètre pour couper les espaces blancs car cela rend les comparaisons de chaînes avec EF beaucoup plus faciles, sans avoir à vérifier s'il y a des espaces blancs inclus lorsque l'expression iqueryable est construite.

7voto

Joey Points 41

LEN coupe les espaces de fin de ligne par défaut, donc j'ai trouvé que ceci fonctionnait si vous les déplacez vers l'avant.

(LEN(REVERSE(TestField))

Donc si tu veux, tu peux dire

SELECT
t.TestField,
LEN(REVERSE(t.TestField)) AS [Reverse],
LEN(t.TestField) AS [Count]
FROM TestTable t
WHERE LEN(REVERSE(t.TestField)) <> LEN(t.TestField)

Ne l'utilisez pas pour les espaces de tête, bien sûr.

12 votes

Maintenant, il coupe leader au lieu des espaces de fin. Même jour, problème différent :)

0 votes

@DaveBoltman Ma suggestion est probablement plus alambiquée encore, mais vous pourriez en plus comparer avec la longueur TRIM'ed.

0 votes

Cela permet d'inverser le bogue où les espaces de tête ne sont pas comptés à la place des espaces de queue. Voir le code suivant : declare @TestField varchar(10); SET @TestField = ' abc '; -- Length with spaces is 5. select LEN(REVERSE(@TestField)) -- Returns 4 select LEN(@TestField) -- Returns 4

5voto

Remus Rusanu Points 159382

Vous devez également vous assurer que vos données sont effectivement enregistrées avec les blancs de fin de ligne. Lorsque PADDING ANSI est désactivé (non par défaut) :

Les blancs de fin de ligne dans les valeurs de caractères insérées dans une colonne varchar sont rognés.

3 votes

Je pense que vous ne devriez pas désactiver ANSI PADDING car ce paramètre est obsolète. L'avoir à une valeur non standard cause de nombreux petits problèmes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X