J'espère que c'est un casse-tête intéressant pour un expert SQL là-bas.
Quand j'exécute la requête suivante, je m'attendrais à ce qu'il ne renvoie aucun résultat. p> Les résultats renvoient une ligne unique: p> Le problème est que les personnes copient et collent des valeurs de courriels, etc. et qu'ils entrent dans le tableau. Je suis en train de regarder comme un problème séparé que je suis ltrim (rtrim (foo)) en tant que déclencheur d'insertion et de mise à jour, mais certains traversent le filet en quelque sorte. P> J'ai besoin d'en savoir plus sur ce comportement et comment je devrais travailler autour de lui. P> Il convient également de noter que Len (FOO) est impair également, comme suit: P> [Foo] [Length] [About]
Bar 3 No spaces
Bar 3 Space Suffix
Bar 4 Space prefix
3 Réponses :
Si vous modifiez la requête en
WHERE RTRIM(t.Foo) = RTRIM(pattern)
La réponse consiste à ajouter la clause suivante: exécutant la requête suivante ... p> ... produit le Résultats suivants ... p> -- Test fVEQ with all 256 characters
DECLARE @Chars TABLE (CharNumber INT NOT NULL)
DECLARE @CharNumber INT = 0
WHILE(@CharNumber <= 255)
BEGIN
INSERT INTO @Chars(CharNumber) VALUES(@CharNumber)
SET @CharNumber = @CharNumber + 1
END
SELECT
CharNumber
, dbo.fVEQ('Bar','Bar' + CHAR(CharNumber)) [fVEQ Trailing Char Test]
, dbo.fVEQ('Bar','Bar') [fVEQ Same test]
, dbo.fVEQ('Bar',CHAR(CharNumber) + 'Bar') [fVEQ Leading Char Test]
FROM @Chars
WHERE (dbo.fVEQ('Bar','Bar' + CHAR(CharNumber)) = 1)
AND (dbo.fVEQ('Bar','Bar') = 0)
AND (dbo.fVEQ('Bar',CHAR(CharNumber) + 'Bar') = 1)
où t.foo = 'bar' et len (t.foo) = len ('bar') code> devrait être suffisant.
Précisément la raison pour laquelle j'ai posé la question. Courez-le et voyez. Ce que nous avons trouvé, c'est que Len ignore les espaces de fuite. La longueur de données ne le fait pas.
La raison pour laquelle les espaces de suivi sont ignorés dans la comparaison des chaînes, est dû à la notion de champs de chaîne de longueur fixe, dans lequel tout contenu plus court que la longueur fixe est automatiquement rembourré à droite avec des espaces. Ces champs de longueur fixe ne peuvent pas distinguer des espaces de fuite significatifs du remplissage. P>
La raison pour laquelle les champs de cordes de longueur fixe existent même, c'est qu'ils améliorent considérablement les performances de manière significative dans de nombreux cas, et lorsque SQL a été conçu, il était courant que les terminaux à base de personnages (qui traitent généralement des espaces de fuite équivalents au rembourrage), des rapports Imprimé avec des polices monospatées (qui utilisaient des espaces de fuite pour le rembourrage et l'alignement) et les formats de stockage et d'échange de données (qui ont utilisé des champs de longueur fixe à la place de délimiteurs étendus et coûteux et de la logique de analyse compliquée), à tous être orientés autour de champs de longueur fixe , donc il y avait une intégration étroite avec ce concept à toutes les étapes du traitement. P>
Lors de la comparaison de deux champs de longueur fixe de même longueur fixe, une comparaison littérale serait bien sûr possible et produirait des résultats corrects. P>
mais lors de la comparaison d'un champ de longueur fixe d'une longueur fixe donnée, à un champ de longueur fixe d'une longueur fixe différente, le comportement souhaité ne serait jamais d'inclure les espaces de fuite dans la comparaison, car deux champs de ce type ne pouvaient jamais correspondre littéralement simplement en raison de leurs longueurs fixes différentes. Le champ plus court pourrait être moulé et rembourré à la longueur du plus long (au moins conceptuellement sinon physiquement), mais l'espace de fuite serait toujours considéré comme un rembourrage plutôt que comme significatif. P>
Lors de la comparaison d'un champ de longueur fixe à un champ de longueur variable, le comportement souhaité ne doit probablement probablement pas inclure les espaces de fuite dans la comparaison. Des approches plus compliquées qui tentent d'attribuer le sens aux espaces de fin du côté de la variable de la comparaison, ne feraient que le coût de la logique de comparaison plus lente et de complexité conceptuelle supplémentaire et potentiel d'erreur. P>
en termes de pourquoi la longueur variable des comparaisons de longueur variable ignorer les espaces de fuite, car les espaces peuvent être significatifs en principe, la raison est probablement de maintenir la cohérence dans le comportement de comparaison, comme lorsqu'il est impliqué, et l'évitement de Le type d'erreur le plus courant, car les espaces de fin sont faux dans des bases de données beaucoup plus souvent qu'ils n'ont significatif. P>
De nos jours, un système de base de données conçu à tous égards à partir de zéro pourrait probablement abandonner des champs à longueur fixe et effectuera probablement toutes les comparaisons littéralement, laissant le développeur pour faire face explicitement avec des espaces de suivi parasites, mais dans mon expérience cela entraînerait un développement supplémentaire. effort et une erreur beaucoup plus fréquente que la disposition actuelle de SQL, où les erreurs de la logique de programme impliquant le mépris silencieux des espaces de fuite ne se produit généralement que lors de la conception de la logique complexe de déchiquetage de chaînes à utiliser contre des données non normalisées (qui est une sorte de données que SQL n'est spécifiquement pas optimisé pour la manipulation). P>
Donc pour être clair, ce n'est pas une fonctionnalité non documentée, mais une caractéristique importante qui existe par la conception. P>
Grande explication Steve. Je me demande ce qui se passe sous le capot, je me demande si la fonction len lit chaque caractère dans un varchar, à partir de droite et de déplacement à gauche à chaque fois jusqu'à ce qu'il atteigne un caractère sans espace, mais la longueur de données peut être lu à gauche mais s'arrête quand elle atteint un caractère qui représente la fin de la chaîne. Je ne suppose pas que vous sauriez savoir comment savoir si vous voulez? De toute façon, merci pour votre réponse brillante.
@Wonderworker, le DataLength code> diffère en ce qu'il renvoie la longueur des octets de la chaîne. Pour les caractères Unicode, chaque caractère logique peut être composé de plusieurs octets.
len code> renvoie la longueur de la chaîne logique, y compris le mépris des espaces de fin. Les deux fonctions ne sont pas des compléments directs de l'autre. Je ne connais pas les implémentations réelles, mais je m'attends à ce que les chaînes soient stockées avec une longueur et que la longueur de données renvoie cette valeur brute, tandis que Len prend la valeur, mais travaille ensuite à l'envers de la droite déduite toute série d'espaces jusqu'à ce qu'il atteigne un non-espace personnage.
Quand les gens copient la pâte .. Il ne doit pas nécessairement être d'espace. Cela peut aussi être des personnages invisibles. Vous devrez peut-être utiliser Patindex pour filtrer notre autre que des alphabets, des chiffres.
Est-ce que cela répond à votre question? comme opérateur et espaces de suivi dans SQL Server
Pour les égaux (
= code>), les espaces de fin sont ignorés. Ils ne sont pas pour des espaces i>. Par conséquent,
'abc' = 'abc' code> Toutefois,
'abc'! = 'Abc' code>. Si vous êtes préoccupé par les utilisateurs saisissant des espaces de début et de suivi des valeurs, vous devez "nettoyer" la valeur avant qu'elle ne soit insérée dans la base de données.
@Smor non, il ne le fait pas
Microsoft a un article de KB à ce sujet, cela aide-t-il? Support. microsoft.com/en-us/help/316626/...
@Larnu citation ... je suis ltrim (rtrim (foo)) en tant que déclencheur d'insertion et de mise à jour, mais certains traversent le filet d'une manière ou d'une autre ....
Ensuite, ce n'est pas une espace blanche, comme le suggère @ganeshchandraskaran. Peut-être qu'il y a des espaces ou des pauses de ligne zéro. Mais dans votre exemple, vous ne réussissez pas, ces valeurs sont les plus définies
'bar' code> et
'bar' code>.
@Tim mylott brillant merci. Je vais garder un œil sur ça.
@Ganesh Chandradeskaran je les ai vérifiées dans un éditeur hexagonal et ils sont le caractère 20 (espace standard)
Ensuite,
Coupez code> (ou
ltrim code> et
rtrim code>) les supprimerait. Montrez-nous un exemple où vous insérez une valeur avec un espace de pointe / de fin, enveloppé b> avec
Garniture code> et il a toujours un espace de pointe / arrière. Sinon, nous ne pouvons donc pas replier le problème, car il est connu des fonctionnalités que les espaces de fuite sont ignorés et dirigent Aren; t.
@Wonderworker je crois que l'espace est ASC (32). Vérifiez le tableau ici ici ASCII.CL
@Ganesh ChandraSekaran C'est correct, cependant, lorsque vous travaillez avec des bits et des octets, il est plus courant (et utile en raison de multiples de 8, 8 bits dans un octet) à penser en hexadécimal sur décimal. L'hexagonal de 32 est 20 I.E. 2 x 16. C'est pourquoi vous avez tendance à voir% 20 dans l'URL et HTML, etc. C'est toujours le caractère 32, mais converti en hex. Expérimentez avec des fichiers mémoire et binaires et vous verrez bientôt pourquoi Hex est si précieux.