Toán tử LIKE có phân biệt chữ hoa chữ thường với MSSQL Server không?


99

Trong tài liệu về toán tử LIKE , không có gì nói về phân biệt chữ hoa chữ thường của nó. Là nó? Làm thế nào để bật / tắt nó?

Tôi đang truy vấn varchar(n)các cột, trên cài đặt Microsoft SQL Server 2005, nếu điều đó quan trọng.


14
Nó phụ thuộc vào sự đối chiếu của cột (hoặc cơ sở dữ liệu) của bạn. Nếu đó là trường hợp nhạy cảm, sau đó LIKElà trường hợp nhạy cảm, nếu nó không phải, sau đó LIKEkhông
Lamak

Kiểm tra tài liệu về đối chiếu SQL-Server msdn.microsoft.com/en-us/library/ms144250%28v=sql.105%29.aspx
GarethD

Mục tiêu của bạn là gì? Bạn muốn nó phân biệt chữ hoa chữ thường hay không phân biệt chữ hoa chữ thường?
Aaron Bertrand

1
Phân biệt chữ hoa chữ thường mặc định cho đối chiếu trên cột mặc định là đối chiếu trên cơ sở dữ liệu. Nó gần như có thể làm tròn được, bạn muốn đi con đường nào?
Tony Hopkinson

Câu trả lời:


101

Nó không phải là toán tử phân biệt chữ hoa chữ thường, nó là chính cột.

Khi cài đặt SQL Server được thực hiện, một đối chiếu mặc định được chọn cho phiên bản. Trừ khi được đề cập rõ ràng theo cách khác (kiểm tra mệnh đề đối chiếu bên dưới) khi một cơ sở dữ liệu mới được tạo, nó kế thừa đối chiếu từ phiên bản và khi một cột mới được tạo, nó kế thừa đối chiếu từ cơ sở dữ liệu mà nó thuộc về.

Một đối chiếu như sql_latin1_general_cp1_ci_aschỉ định cách xử lý nội dung của cột. CI là viết tắt của phân biệt chữ hoa chữ thường và AS là viết tắt của phân biệt trọng âm.

Danh sách đầy đủ các ảnh ghép có sẵn tại https://msdn.microsoft.com/en-us/library/ms144250(v=sql.105).aspx

(a) Để kiểm tra đối chiếu phiên bản

select serverproperty('collation')

(b) Để kiểm tra đối chiếu cơ sở dữ liệu

select databasepropertyex('databasename', 'collation') sqlcollation

(c) Để tạo cơ sở dữ liệu bằng cách sử dụng đối chiếu khác

create database exampledatabase
collate sql_latin1_general_cp1_cs_as 

(d) Để tạo một cột bằng cách sử dụng một đối chiếu khác

create table exampletable (
    examplecolumn varchar(10) collate sql_latin1_general_cp1_ci_as null
)

(e) Để sửa đổi đối chiếu cột

alter table exampletable
alter column examplecolumn varchar(10) collate sql_latin1_general_cp1_ci_as null

Có thể thay đổi một thể hiện và đối chiếu cơ sở dữ liệu nhưng nó không ảnh hưởng đến các đối tượng đã tạo trước đó.

Cũng có thể thay đổi đối chiếu cột nhanh chóng để so sánh chuỗi, nhưng điều này rất không được khuyến khích trong môi trường sản xuất vì nó cực kỳ tốn kém.

select
  column1 collate sql_latin1_general_cp1_ci_as as column1
from table1

5
Có vẻ như dải ký tự như [A-Z]luôn phân biệt chữ hoa chữ thường. [ABCDEFGHIJKLMNOPQRSŠTUVWXYZŽÅÄÖ]tuy nhiên dường như tuân theo đối chiếu.
jumxozizi,

1
Ngoài ra, bạn có thể truy vấn các trường hợp nhạy cảm một cột cụ thể với một cái gì đó như thế này:select COLLATION_NAME, iif(cast(COLLATIONPROPERTY(COLLATION_NAME, 'ComparisonStyle') as int) & 1 = 0, 'case sensitive', 'case insensitive') from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'exampletable' and COLUMN_NAME = 'examplecolumn'
Jeppe Stig Nielsen

@jumxozizi Tôi đã thêm đề xuất của bạn vào câu trả lời.
John Zabroski

@JeppeStigNielsen Tôi đã thêm đề xuất của bạn vào câu trả lời.
John Zabroski

18

Tất cả những gì nói về đối chiếu có vẻ hơi phức tạp. Tại sao không chỉ sử dụng một cái gì đó như:

IF UPPER(@@VERSION) NOT LIKE '%AZURE%'

Khi đó séc của bạn không phân biệt chữ hoa chữ thường bất kể đối chiếu


10
Bởi vì điều này không đáng tin cậy. Ví dụ của bạn sử dụng một biến và một ký tự đại diện đứng đầu. Nhưng đối với một cột được lập chỉ mục với đối chiếu không phân biệt chữ hoa chữ thường like 'a%'có thể sử dụng chỉ mục và upperphiên bản thì không.
Martin Smith

3
Câu hỏi đặt ra là liệu liketoán tử có phân biệt chữ hoa chữ thường hay không .
jumxozizi

Bạn cần phải biết đối chiếu, nếu không làm điều này có thể là vô nghĩa. Ví dụ: nếu cột được truy vấn chống lại các mục đích sử dụng Latin1_General_CI_AS, thì thực hiện UPPER(@@VALUE) NOT LIKE '%SOMETHING%'hoặc @@COLUMN NOT LIKE '%SOMETHING%'không liên quan: kết quả sẽ giống nhau.
rsenna

13

Bạn có một tùy chọn để xác định thứ tự đối chiếu tại thời điểm xác định bảng của mình. Nếu bạn xác định một thứ tự phân biệt chữ hoa chữ thường, thì LIKEnhà điều hành của bạn sẽ hành xử theo cách phân biệt chữ hoa chữ thường; nếu bạn xác định một thứ tự đối chiếu không phân biệt chữ hoa chữ thường, LIKEtoán tử cũng sẽ bỏ qua chữ hoa chữ thường :

CREATE TABLE Test (
    CI_Str VARCHAR(15) COLLATE Latin1_General_CI_AS -- Case-insensitive
,   CS_Str VARCHAR(15) COLLATE Latin1_General_CS_AS -- Case-sensitive
);

Đây là bản demo nhanh trên sqlfiddle hiển thị kết quả của thứ tự đối chiếu trên các tìm kiếm với LIKE.


12

Nếu bạn muốn thực hiện tìm kiếm phân biệt chữ hoa chữ thường mà không thay đổi đối chiếu của cột / cơ sở dữ liệu / máy chủ, bạn luôn có thể sử dụng COLLATEmệnh đề, ví dụ:

USE tempdb;
GO
CREATE TABLE dbo.foo(bar VARCHAR(32) COLLATE Latin1_General_CS_AS);
GO
INSERT dbo.foo VALUES('John'),('john');
GO
SELECT bar FROM dbo.foo 
  WHERE bar LIKE 'j%';
-- 1 row

SELECT bar FROM dbo.foo 
  WHERE bar COLLATE Latin1_General_CI_AS LIKE 'j%';
-- 2 rows

GO    
DROP TABLE dbo.foo;

Cũng hoạt động theo cách khác, nếu cột / cơ sở dữ liệu / máy chủ của bạn phân biệt chữ hoa chữ thường và bạn không muốn tìm kiếm phân biệt chữ hoa chữ thường, ví dụ:

USE tempdb;
GO
CREATE TABLE dbo.foo(bar VARCHAR(32) COLLATE Latin1_General_CI_AS);
GO
INSERT dbo.foo VALUES('John'),('john');
GO
SELECT bar FROM dbo.foo 
  WHERE bar LIKE 'j%';
-- 2 rows

SELECT bar FROM dbo.foo 
  WHERE bar COLLATE Latin1_General_CS_AS LIKE 'j%';
-- 1 row

GO
DROP TABLE dbo.foo;

Hãy cẩn thận trong truy vấn cuối cùng nếu bạn sử dụng WHERE bar COLLATE Latin1_General_CS_AS LIKE '[j-k]%'nó sẽ trả về Johnvì trong đối chiếu này vốn đối chiếu Jnằm giữa chữ thường jvà chữ thường k. Nó giống như aAbBcC...jJkKlLmM...điều không rõ ràng. Nó có vẻ Latin1_General_BINdễ đoán hơn với các tìm kiếm phạm vi với toán tử LIKE.
wqw

7

Các likenhà điều hành phải mất hai chuỗi. Các chuỗi này phải có các đối chiếu tương thích, điều này được giải thích ở đây .

Theo tôi, mọi thứ sau đó trở nên phức tạp. Truy vấn sau trả về lỗi cho biết rằng các đối chiếu không tương thích:

select *
from INFORMATION_SCHEMA.TABLES
where 'abc' COLLATE SQL_Latin1_General_CP1_CI_AS like 'ABC' COLLATE SQL_Latin1_General_CP1_CS_AS

Trên một máy ngẫu nhiên ở đây, đối chiếu mặc định là SQL_Latin1_General_CP1_CI_AS. Truy vấn sau thành công, nhưng không trả về hàng nào:

select *
from INFORMATION_SCHEMA.TABLES
where 'abc' like 'ABC' COLLATE SQL_Latin1_General_CP1_CS_AS

Các giá trị "abc" và "ABC" không khớp trong thế giới phân biệt chữ hoa chữ thường.

Nói cách khác, có sự khác biệt giữa không có đối chiếu và sử dụng đối chiếu mặc định. Khi một bên không có đối chiếu, thì nó được "gán" một đối chiếu rõ ràng từ phía bên kia.

(Kết quả giống nhau khi đối chiếu rõ ràng ở bên trái.)


Bạn có thể tạo lại lỗi đối với bảng KHÔNG phải là đối tượng hệ thống như INFORMATION_SCHEMA.TABLES không?
Aaron Bertrand

@AaronBertrand. . . Vâng tôi có thể. Cơ sở dữ liệu có bị hỏng không;)?
Gordon Linoff

Tôi không biết, tôi đang sử dụng thiết bị di động và không thể khởi động máy ảo Windows. Tôi chỉ không biết rằng toàn bộ mô tả của bạn là chính xác về mặt kỹ thuật.
Aaron Bertrand

4

Hãy thử chạy,

SELECT SERVERPROPERTY('COLLATION')

Sau đó, tìm hiểu xem đối chiếu của bạn có phân biệt chữ hoa chữ thường hay không.



0

Bạn có thể dễ dàng thay đổi đối chiếu trong Microsoft SQL Server Management studio.

  • nhấp chuột phải vào bảng -> thiết kế.
  • chọn cột của bạn, cuộn xuống thuộc tính cột của tôi để Đối chiếu.
  • Đặt tùy chọn sắp xếp của bạn bằng cách chọn "Phân biệt chữ hoa chữ thường"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.