SQL Server tự động cắt giá trị varchar trong so sánh bằng nhau nhưng không giống như so sánh


13

Tôi đã bắt gặp một số hành vi thú vị trên SQL Server (được quan sát vào năm 2005 và 2012) ngày hôm nay mà tôi hy vọng ai đó có thể giải thích.

Một truy vấn thực hiện so sánh bằng cách sử dụng =trên trường NVARCHAR đã bỏ qua khoảng trắng theo sau trong chuỗi (hoặc tự động cắt xén giá trị trước khi so sánh) nhưng cùng một truy vấn sử dụng liketoán tử đã không bỏ qua khoảng trắng. Đối chiếu đang được sử dụng là Latin1_General_CI_AS vào năm 2012.

Hãy xem xét Fiddle SQL này: http://sqlfiddle.com/#!6/72262/4

Lưu ý rằng liketoán tử không trả về kết quả cho chuỗi dấu cách, nhưng =toán tử thực hiện. Tại sao lại thế này?

Điểm thưởng: Tôi không thể sao chép điều này trên trường VARCHAR, tôi đã nghĩ rằng một không gian sẽ được xử lý theo cùng một cách trong cả hai loại dữ liệu - điều này có đúng không?


Tôi đang tìm cách viết một ràng buộc kiểm tra rằng một chuỗi đã được cắt. Tôi đã tìm thấy một cách giải quyết đó là kiểm tra xem MyString+'x' = ltrim(rtrim(MyString))+'x'như được đề xuất trên blog này
default.kramer

Câu trả lời:


15

Câu trả lời ban đầu của tôi cho thấy rằng cờ ANSI_PADDING được đặt thành TẮT có thể là nguyên nhân cho sự khác biệt trong hành vi. Tuy nhiên, điều này là không chính xác; cờ này chỉ có tác dụng trong việc lưu trữ, nhưng không so sánh bình đẳng.

Sự khác biệt bắt nguồn từ việc Microsoft thực hiện tiêu chuẩn SQL . Tiêu chuẩn quy định rằng khi kiểm tra sự bằng nhau, cả hai chuỗi bên trái và bên phải của toán tử đẳng thức phải được đệm để có cùng độ dài . Điều này giải thích các kết quả sau:

insert into test_padding (varchar_clmn, nvarchar_clmn) values ('space ', 'nspace ')
go
-- equality for varchar column
select count(*) from test_padding where varchar_clmn = 'space' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space    ' --returns 1
-- equality for nvarchar column
select count(*) from test_padding where nvarchar_clmn = 'nspace' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace    ' --returns 1

Toán tử THÍCH không đệm toán hạng của nó. Nó cũng hoạt động khác nhau cho các loại VARCHARNVARCHARcột :

-- likeness for varchar column
select count(*) from test_padding where varchar_clmn like 'space' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space    ' -- returns 0
-- likeness for nvarchar column
select count(*) from test_padding where nvarchar_clmn like 'nspace' -- returns 0
select count(*) from test_padding where nvarchar_clmn like 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn like 'nspace    ' -- returns 0

Hành vi của toán tử THÍCH cho loại ASCII là dành riêng cho SQL Server; đối với loại Unicode, nó tuân thủ ANSI.


4

SQL ra đời trong thời đại mà hầu hết các ngôn ngữ xử lý dữ liệu sử dụng độ dài cố định cho mọi trường / biến. Tự động đệm các trường văn bản có thêm khoảng trắng cũng là một phần của bức tranh đó. Để phù hợp với hành vi đó, loại CHAR CHAR gốc được xác định rõ ràng cho toán tử '=' của nó để bỏ qua các khoảng trắng ở cuối. (Nếu bạn thấy lạ, hãy cho tôi xem một trường hợp hấp dẫn trong đó các dấu cách được thêm vào một văn bản có ý nghĩa kinh doanh thực tế .)

Các kiểu SQL CHAR đã phát triển theo tất cả các hướng kể từ đó, nhưng không thể tin được rằng một số loại dữ liệu hiện đại hơn vẫn còn thừa hưởng một số đặc điểm từ các tiền thân lịch sử của chúng.


"Chỉ cho tôi một trường hợp hấp dẫn trong đó các dấu cách nối vào văn bản có ý nghĩa kinh doanh thực tế thực sự" - lưu trữ dữ liệu có ý nghĩa khoảng trắng, chẳng hạn như đầu ra của bàn điều khiển thô và các đoạn XML không an toàn trước.
Đại

1

Trong tài liệu về THÍCH (Transact-SQL) , Microsoft viết (nhấn mạnh của tôi):

Kết hợp mẫu bằng cách sử dụng THÍCH

THÍCH hỗ trợ khớp mẫu ASCII và khớp mẫu Unicode. Khi tất cả các đối số ... là các kiểu dữ liệu ký tự ASCII, khớp mẫu ASCII được thực hiện. Nếu bất kỳ một trong các đối số thuộc loại dữ liệu Unicode, tất cả các đối số được chuyển đổi sang kết hợp mẫu Unicode và Unicode được thực hiện. Khi bạn sử dụng dữ liệu Unicode ... với THÍCH, khoảng trống theo sau là rất quan trọng; tuy nhiên, đối với dữ liệu không phải là Unicode, khoảng trống theo dõi là không đáng kể. Unicode THÍCH tương thích với tiêu chuẩn ISO. ASCII THÍCH tương thích với các phiên bản trước của SQL Server.

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.