2015-04-02 2 views
5

Ho difficoltà a capire perché una condizione LIKE su un'emoji di 4 B (http://emojipedia.org/eyes/) restituisce tutte le righe nella tabella.SQL Server 2014 LIKE con carattere di larghezza 4 B restituisce l'intera tabella

-- The DB collation is Finnish_Swedish_CI_AS 
CREATE TABLE #Test 
(
    Number int identity, 
    Value nvarchar(20) NOT NULL 
); 
GO 

INSERT INTO #Test VALUES (''); 
INSERT INTO #Test VALUES ('a'); 
INSERT INTO #Test VALUES ('b'); 
INSERT INTO #Test VALUES ('c'); 
INSERT INTO #Test VALUES (''); -- should be http://emojipedia.org/eyes/ 
GO 

select * from #Test where Value like '%%' 
select * from #Test where Value like N'%%' 
GO 

DROP TABLE #Test; 
GO 

Il risultato della prima selezione è la singola riga di emoji. Tuttavia, il risultato della seconda selezione, in cui la stringa è contrassegnata come UNICODE con il prefisso N, sono tutte le righe.

Perché la seconda selezione corrisponde a tutte le righe nella tabella?

Scenario attuale Ho un'applicazione Web in cui gli utenti possono cercare una directory e, se cercano un'emoji, viene restituita l'intera tabella anziché le righe corrispondenti.

ASP.NET MVC 5 web application <-> Web Api 2 <-> EF -> SQL Server 

Aggiornamento La mia prova SQL è corretto, come @deroby rilevare le INSERT dichiarazioni devono essere contrassegnati con N '...' per essere inserita correttamente come Unicode.

Soluzione Come @deroby ha dichiarato che sembra essere un problema di collazione, cambiando in Finnish_Swedish_100_CI_AS sembra che le cose funzionino come previsto.

select * from #Test where Value like N'%%' COLLATE Finnish_Swedish_100_CI_AS 

risposta

3

Diventa ancora più divertente quando si aggiunge

INSERT INTO #Test VALUES (''); -- should be http://emojipedia.org/eyes/ 

Il tuo primo SELECT sarà ora tornare entrambi i record emoji; anche se sembreranno sbagliati. Il motivo è che sia sia sono valori varchar() non validi. In questo modo, viene inserito un segnaposto nel database (mostrato come ??).

Ora, se fate il vostro inserti 'correttamente' e inserire i dati corretti stringhe Unicode, quindi le cose funzionano molto meglio:

INSERT INTO #Test VALUES (N''); 
INSERT INTO #Test VALUES (N'a'); 
INSERT INTO #Test VALUES (N'b'); 
INSERT INTO #Test VALUES (N'c'); 
INSERT INTO #Test VALUES (N''); -- should be http://emojipedia.org/eyes/ 
INSERT INTO #Test VALUES (N''); -- should be http://emojipedia.org/eyes/ 

select * from #Test -- returns everything 
select * from #Test where Value like '%%' -- returns nothing (because it looks for the '??' placeholder 
select * from #Test where Value like N'%%' -- returns just one line 

PS: è così che funziona sul mio SQL2012 qui (Latin1_General_BIN).

Perché la seconda selezione corrisponde a tutte le righe nella tabella?

Che non riesca a spiegare neanche; per me non è così. Quindi immagino che sia un problema di collazione in cui queste emoji sono tutte considerate uguali.

E infatti, fare il test

select * from #Test where Value like N'%%' COLLATE Finnish_Swedish_CI_AS 
select * from #Test where Value like N'%%' COLLATE Latin1_General_BIN 

mostra che la ragione ha bisogno di essere cercato qui. Per quanto riguarda il perché, non ne ho idea.