it-swarm-eu.dev

Chování Varchar s mezerami na konci

Když používám Varchar s mezerami, ignoruje mezery na konci.

ex:

declare @X varchar(50)

Tento...

set  @X= 'John'

...je stejné jako...

set @X= 'John           '

Považuje je za rovnocenné. Jak mohu přimět systém, aby je rozpoznal jako odlišný?

14
AMH

Všechno odpovídá standardu ANSI:

Vysvětlení koncových mezer :

SQL Server se řídí specifikací ANSI/ISO SQL-92 (oddíl 8.2, Obecná pravidla # 3) o tom, jak porovnávat řetězce s mezerami. Standard ANSI vyžaduje čalounění znakových řetězců používaných ve srovnání tak, aby se jejich délky shodovaly před jejich porovnáním. Výplň přímo ovlivňuje sémantiku predikátů klauzulí WHERE a HAVING a dalších porovnávání řetězců Transact-SQL. Například Transact-SQL považuje řetězce 'abc' a 'abc' za ekvivalentní pro většinu srovnávacích operací.

Jedinou výjimkou z tohoto pravidla je LIKE predikát. Pokud na pravé straně výrazu LIKE predikát obsahuje hodnotu s koncové mezery, SQL Server nevkládá dvě hodnoty na stejnou délku před provedením porovnání. Protože účelem predikátu LIKE je podle definice usnadnit vyhledávání vzorů spíše než jednoduché testy rovnosti řetězců, neporuší to výše uvedenou specifikaci ANSI SQL-92.

Zde je známý příklad všech výše uvedených případů:

DECLARE @a VARCHAR(10)
DECLARE @b varchar(10)

SET @a = '1'
SET @b = '1 ' --with trailing blank

SELECT 1
WHERE 
    @a = @b 
AND @a NOT LIKE @b
AND @b LIKE @a

Zde je několik podrobnějších informací o koncových mezerách a klauzuli LIKE .

[~ # ~], ale [~ # ~] , pokud je chcete odlišit - můžete se rozhodnout použít funkci DATALENGTH místo LEN, protože

SELECT 1 WHERE LEN('John ') = LEN('John')

dá vám místo 1 místo

SELECT 1 WHERE DATALENGTH('John ') = DATALENGTH('John')

Řešení je

  • použít funkci DATALENGTH k rozlišení mezi řetězci
  • vložit řetězec do typu NVARCHAR - může být lepší deklarovat tento typ k parametru SP
23
Oleg Dok