Làm cách nào để tạo một truy vấn SQL (MS SQL Server) trong đó mệnh đề "where" không phân biệt chữ hoa chữ thường?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Tôi muốn kết quả trở lại bỏ qua trường hợp
Làm cách nào để tạo một truy vấn SQL (MS SQL Server) trong đó mệnh đề "where" không phân biệt chữ hoa chữ thường?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Tôi muốn kết quả trở lại bỏ qua trường hợp
Câu trả lời:
Trong cấu hình mặc định của một cơ sở dữ liệu SQL Server, so sánh chuỗi là case-insensitive. Nếu cơ sở dữ liệu của bạn ghi đè cài đặt này (thông qua việc sử dụng đối chiếu thay thế), thì bạn sẽ cần chỉ định loại đối chiếu nào sẽ sử dụng trong truy vấn của mình.
SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS
Lưu ý rằng đối chiếu tôi đã cung cấp chỉ là một ví dụ (mặc dù nó có nhiều khả năng hoạt động tốt cho bạn). Bạn có thể tìm thấy một phác thảo kỹ lưỡng hơn về các đối chiếu SQL Server tại đây .
UPPER
hoặc LOWER
trường hợp sau đó sử dụng LIKE
để tìm kiếm?
Thông thường, các phép so sánh chuỗi không phân biệt chữ hoa chữ thường. Nếu cơ sở dữ liệu của bạn được định cấu hình để đối chiếu phân biệt chữ hoa chữ thường, bạn cần buộc phải sử dụng phân biệt chữ hoa chữ thường:
SELECT balance FROM people WHERE email = 'billg@microsoft.com'
COLLATE SQL_Latin1_General_CP1_CI_AS
Tôi đã tìm thấy một giải pháp khác ở nơi khác; đó là, để sử dụng
upper(@yourString)
nhưng tất cả mọi người ở đây đang nói rằng, trong SQL Server, nó không quan trọng bởi vì nó bỏ qua trường hợp nào? Tôi khá chắc chắn rằng cơ sở dữ liệu của chúng tôi phân biệt chữ hoa chữ thường.
2 câu trả lời hàng đầu (của Adam Robinson và Andrejs Cainikovs ) là tương đối, đúng, ở chỗ chúng hoạt động về mặt kỹ thuật, nhưng lời giải thích của chúng sai và do đó có thể gây hiểu lầm trong nhiều trường hợp. Ví dụ, trong khi SQL_Latin1_General_CP1_CI_AS
đối chiếu sẽ hoạt động trong nhiều trường hợp, nó không nên được giả định là đối chiếu không phân biệt chữ hoa chữ thường thích hợp. Trên thực tế, do OP đang làm việc trong cơ sở dữ liệu với đối chiếu phân biệt chữ hoa chữ thường (hoặc có thể là nhị phân), chúng tôi biết rằng OP không sử dụng đối chiếu là mặc định cho rất nhiều cài đặt (đặc biệt là bất kỳ cài đặt nào được cài đặt trên HĐH. sử dụng tiếng Anh-Mỹ là ngôn ngữ): SQL_Latin1_General_CP1_CI_AS
. Chắc chắn, OP có thể được sử dụng SQL_Latin1_General_CP1_CS_AS
, nhưng khi làm việc vớiVARCHAR
dữ liệu, điều quan trọng là không thay đổi trang mã vì nó có thể dẫn đến mất dữ liệu và điều đó được kiểm soát bởi ngôn ngữ / văn hóa của đối chiếu (ví dụ: Latin1_General vs French vs Hebrew, v.v.). Vui lòng xem điểm # 9 bên dưới.
Bốn câu trả lời còn lại sai ở các mức độ khác nhau.
Tôi sẽ làm rõ tất cả những hiểu lầm ở đây để bạn đọc có thể đưa ra những lựa chọn phù hợp / hiệu quả nhất.
Không sử dụng UPPER()
. Đó hoàn toàn là việc làm thêm không cần thiết. Sử dụng một COLLATE
mệnh đề. Một phép so sánh chuỗi cần được thực hiện trong cả hai trường hợp, nhưng việc sử dụng UPPER()
cũng phải kiểm tra từng ký tự để xem có ánh xạ chữ hoa hay không, sau đó thay đổi nó. Và bạn cần làm điều này trên cả hai mặt. Việc thêm COLLATE
chỉ đơn giản là hướng quá trình xử lý để tạo ra các khóa sắp xếp bằng cách sử dụng một bộ quy tắc khác so với mặc định. Sử dụng COLLATE
chắc chắn hiệu quả hơn (hoặc "hiệu quả", nếu bạn thích từ đó :) so với sử dụng UPPER()
, như đã được chứng minh trong tập lệnh thử nghiệm này (trên PasteBin) .
Cũng có một vấn đề được @Ceisc lưu ý về câu trả lời của @ Danny:
Trong một số ngôn ngữ, chuyển đổi trường hợp không đi vòng lại. tức là LOWER (x)! = LOWER (UPPER (x)).
Ví dụ phổ biến là chữ hoa "İ" trong tiếng Thổ Nhĩ Kỳ.
Không, đối chiếu không phải là cài đặt toàn cơ sở dữ liệu, ít nhất là không phải trong ngữ cảnh này. Có một đối chiếu mặc định ở cấp cơ sở dữ liệu và nó được sử dụng làm mặc định cho các cột đã thay đổi và mới được tạo không chỉ định COLLATE
mệnh đề (có thể là nơi xuất phát quan niệm sai lầm phổ biến này), nhưng nó không ảnh hưởng trực tiếp đến các truy vấn trừ khi bạn so sánh các ký tự và biến chuỗi với các ký tự và biến chuỗi khác hoặc bạn đang tham chiếu đến siêu dữ liệu cấp cơ sở dữ liệu.
Không, đối chiếu không phải cho mỗi truy vấn.
Các đối chiếu là trên mỗi vị từ (tức là toán hạng thứ gì đó) hoặc biểu thức, không phải trên mỗi truy vấn. Và điều này đúng với toàn bộ truy vấn, không chỉ WHERE
mệnh đề. Điều này bao gồm các JOIN, GROUP BY, ORDER BY, PARTITION BY, v.v.
Không, không chuyển đổi thành VARBINARY
(ví dụ convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
) vì những lý do sau:
_BIN2
nếu bạn đang sử dụng SQL Server 2008 hoặc mới hơn, nếu không, bạn không có lựa chọn nào khác ngoài sử dụng một kết thúc bằng _BIN
. Nếu dữ liệu là dữ liệu NVARCHAR
thì không quan trọng bạn sử dụng ngôn ngữ nào vì chúng đều giống nhau trong trường hợp đó, do đó Latin1_General_100_BIN2
luôn hoạt động. Nếu dữ liệu là VARCHAR
, bạn phải sử dụng locale tương tự mà các dữ liệu hiện đang trong (ví dụ Latin1_General
, French
, Japanese_XJIS
, vv) vì miền địa phương xác định trang mã được sử dụng, và thay đổi trang mã có thể làm thay đổi dữ liệu (tức là mất dữ liệu).CONVERT()
nó sẽ sử dụng giá trị mặc định 30. Điều nguy hiểm là, nếu chuỗi có thể lớn hơn 30 byte, nó sẽ bị cắt ngắn một cách âm thầm và bạn có thể sẽ nhận được kết quả không chính xác từ vị từ này.Không, LIKE
không phải lúc nào cũng phân biệt chữ hoa chữ thường. Nó sử dụng đối chiếu của cột được tham chiếu hoặc đối chiếu của cơ sở dữ liệu nếu một biến được so sánh với một chuỗi ký tự hoặc đối chiếu được chỉ định thông qua COLLATE
mệnh đề tùy chọn .
LCASE
không phải là một chức năng của SQL Server. Nó dường như là Oracle hoặc MySQL. Hoặc có thể là Visual Basic?
Vì ngữ cảnh của câu hỏi là so sánh một cột với một chuỗi theo nghĩa đen, nên cả đối chiếu của cá thể (thường được gọi là "máy chủ") và đối chiếu của cơ sở dữ liệu đều không có tác động trực tiếp nào ở đây. Các đối chiếu được lưu trữ trên mỗi cột và mỗi cột có thể có một đối chiếu khác nhau và những đối chiếu đó không cần phải giống đối chiếu mặc định của cơ sở dữ liệu hoặc đối chiếu của phiên bản. Chắc chắn, đối chiếu phiên bản là mặc định cho những gì một cơ sở dữ liệu mới được tạo sẽ sử dụng làm đối chiếu mặc định của nó nếu COLLATE
mệnh đề không được chỉ định khi tạo cơ sở dữ liệu. Và tương tự như vậy, đối chiếu mặc định của cơ sở dữ liệu là những gì một cột được thay đổi hoặc mới tạo sẽ sử dụng nếu COLLATE
mệnh đề không được chỉ định.
Bạn nên sử dụng đối chiếu không phân biệt chữ hoa chữ thường giống như đối chiếu của cột. Sử dụng truy vấn sau để tìm đối chiếu của cột (thay đổi tên bảng và tên giản đồ):
SELECT col.*
FROM sys.columns col
WHERE col.[object_id] = OBJECT_ID(N'dbo.TableName')
AND col.[collation_name] IS NOT NULL;
Sau đó, chỉ cần thay đổi _CS
được _CI
. Vì vậy, Latin1_General_100_CS_AS
sẽ trở thành Latin1_General_100_CI_AS
.
Nếu cột đang sử dụng đối chiếu nhị phân (kết thúc bằng _BIN
hoặc _BIN2
), thì hãy tìm đối chiếu tương tự bằng cách sử dụng truy vấn sau:
SELECT *
FROM sys.fn_helpcollations() col
WHERE col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
Ví dụ: giả sử cột đang sử dụng Japanese_XJIS_100_BIN2
, hãy làm như sau:
SELECT *
FROM sys.fn_helpcollations() col
WHERE col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%';
Để biết thêm thông tin về ảnh ghép, bảng mã, v.v., vui lòng truy cập: Thông tin ảnh ghép
Không, chỉ sử dụng LIKE
sẽ không hoạt động. LIKE
tìm kiếm các giá trị khớp chính xác với mẫu đã cho của bạn. Trong trường hợp này LIKE
sẽ chỉ tìm thấy văn bản 'sOmeVal' chứ không phải 'someval'.
Một giải pháp thực tế đang sử dụng LCASE()
hàm. LCASE('sOmeVal')
lấy chuỗi chữ thường của văn bản của bạn: 'someval'. Nếu bạn sử dụng chức năng này cho cả hai mặt so sánh của mình, nó hoạt động:
SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')
Câu lệnh so sánh hai chuỗi chữ thường để 'sOmeVal' của bạn sẽ khớp với mọi ký hiệu khác của 'someval' (ví dụ: 'Someval', 'sOMEVAl', v.v.).
LCASE()
trong SQL Server (ít nhất thì tôi không thấy). Tôi nghĩ câu trả lời này dành cho một RDBMS hoàn toàn khác. Vui lòng xem câu trả lời của tôi để biết rõ hơn về so sánh chuỗi.
Bạn có thể buộc phân biệt chữ hoa chữ thường, truyền thành một varbinary như vậy:
SELECT * FROM myTable
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
Bạn đang sử dụng cơ sở dữ liệu nào? Với MS SQL Server, đó là một cài đặt toàn bộ cơ sở dữ liệu hoặc bạn có thể sử dụng nó cho mỗi truy vấn với từ khóa COLLATE.
WHERE
câu lệnh và sẽ ảnh hưởng đến tất cả cácWHERE
mệnh đề, đúng không?