Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL Server Like Query, Groß-/Kleinschreibung nicht beachten

Problem:

Ursache:Spalte 'Name' hat eine Groß-/Kleinschreibung (CI ) Sortierung.

Lösung:Sie müssen ein CS verwenden Sortierung:SELECT * FROM fn_helpcollations() WHERE description LIKE N'%case-sensitive%' .

Hinweis:Es gibt eine Sortierung auf Datenbankebene und eine Sortierung auf Spaltenebene. Und es gibt auch eine Sortierung auf Serverebene.

SELECT  DATABASEPROPERTYEX(DB_NAME(), 'Collation') AS DatabaseCollation
/*
-- Sample output (my database)
DatabaseCollation
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/

SELECT  col.collation_name AS ColumnCollation
FROM    sys.columns col
WHERE   col.object_id = OBJECT_ID(N'dbo.Table_2') 
AND     col.name = N'Name'
/*
-- Sample output (my database)
ColumnCollation
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/

Das einfache Ändern der Datenbanksortierung wird NICHT Ändern Sie die Sortierung für vorhandene Benutzertabellen und -spalten:

Quelle

Nach Ändern der Datenbanksortierung , lautet die Ausgabe der obigen Abfragen:

/*
DatabaseCollation -- changed
----------------------------
SQL_Latin1_General_CP1_CS_AS
*/

/*
ColumnCollation -- no change
----------------------------
SQL_Latin1_General_CP1_CI_AS
*/

und, wie Sie die Sortierung der Spalte Name sehen können bleibt CI.

Darüber hinaus wirkt sich das Ändern der Datenbanksortierung nur auf die neu erstellten Tabellen und Spalten aus. Daher könnte das Ändern der Datenbanksortierung zu seltsamen Ergebnissen führen (meiner Meinung nach ), weil einige [N][VAR]CHAR Spalten werden CI sein und die neuen Spalten werden CS sein.

Ausführliche Lösung #1:Wenn nur einige Abfragen für die Spalte Name muss CS sein dann werde ich WHERE umschreiben Klausel dieser Abfragen also:

SELECT  Name 
FROM    dbo.Table_2
WHERE   Name LIKE 'Joe' AND Name LIKE 'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS

Dadurch wird SQL Server geändert, um eine Index Seek durchzuführen in Spalte Name (darin befindet sich ein Index auf Spalte Name ). Außerdem enthält der Ausführungsplan eine implizite Konvertierung (siehe Predicate Eigenschaft für Index Seek ) wegen folgendem Prädikat Name = N'Joe' COLLATE SQL_Latin1_General_CP1_CS_AS .

Detaillösung #2:wenn alle Abfragen nach Spalte Name muss CS sein, dann ändere ich die Sortierung nur für die Spalte Name also:

-- Drop all objects that depends on this column (ex. indexes, constraints, defaults)
DROP INDEX IX_Table_2_Name ON dbo.Table_2

-- Change column's collation
ALTER TABLE dbo.Table_2
ALTER COLUMN Name VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CS_AS
-- Replace VARCHAR(50) with proper data type and max. length
-- Replace COLLATE SQL_Latin1_General_CP1_CS_AS with the right CS collation

-- Recreate all objects that depends on column Name (ex. indexes, constraints, defaults)
CREATE INDEX IX_Table_2_Name ON dbo.Table_2 (Name)

-- Test query
SELECT  Name 
FROM    dbo.Table_2
WHERE   Name LIKE 'Joe'