2012-02-27 33 views
8

Tôi đang sử dụng Microsoft SQL Server 2008 R2 (với gói dịch vụ/bản vá mới nhất) và collation cơ sở dữ liệu là SQL_Latin1_General_CP1_CI_AS.Hành vi của chỉ mục duy nhất, cột VARCHAR và (trống)

Các mã sau đây:

SET ANSI_PADDING ON; 
GO 

CREATE TABLE Test (
    Code VARCHAR(16) NULL 
); 
CREATE UNIQUE INDEX UniqueIndex 
    ON Test(Code); 

INSERT INTO Test VALUES ('sample'); 
INSERT INTO Test VALUES ('sample '); 

SELECT '>' + Code + '<' FROM Test WHERE Code = 'sample  '; 
GO 

tạo ra kết quả như sau:

(1 row (s) bị ảnh hưởng)

Msg 2601, Level 14, State 1, Line 8

Không thể chèn hàng khóa trùng lặp trong đối tượng 'dbo.Test' với chỉ mục duy nhất 'UniqueIndex'. Giá trị khóa trùng lặp là (mẫu).

Tuyên bố đã bị chấm dứt.

‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐

> mẫu <

(1 row (s) bị ảnh hưởng)

Câu hỏi của tôi s là:

  1. Tôi cho rằng chỉ mục không thể lưu trữ dấu cách. Bất cứ ai có thể chỉ cho tôi tài liệu chính thức xác định/xác định hành vi này?
  2. Có một cài đặt để thay đổi hành vi này, có nghĩa là, biến nó thành 'mẫu' và 'mẫu' thành hai giá trị khác nhau (theo cách này) để cả hai có thể nằm trong chỉ mục.
  3. Tại sao Earth lại là SELECT trả về hàng? SQL Server phải làm một cái gì đó thực sự hài hước/thông minh với các khoảng trống trong mệnh đề WHERE bởi vì nếu tôi loại bỏ tính duy nhất trong chỉ mục, cả hai INSERT sẽ chạy OK và SELECT sẽ trả về hai hàng!

Mọi trợ giúp/con trỏ đi đúng hướng sẽ được đánh giá cao. Cảm ơn.

Trả lời

11

Trailing blanks explained:

SQL Server theo ANSI/ISO SQL-92 đặc điểm kỹ thuật (Phần 8.2, , chung quy tắC# 3) về cách so sánh chuỗi với không gian. Tiêu chuẩn ANSI yêu cầu đệm cho các ký tự chuỗi được sử dụng để so sánh sao cho độ dài của chúng phù hợp trước khi so sánh chúng. Phần đệm trực tiếp ảnh hưởng đến ngữ nghĩa của các mệnh đề mệnh đề WHERE và HAVING và các chuỗi so sánh Transact-SQL khác . Ví dụ, Transact-SQL xem xét các chuỗi 'abc' và 'abc' tương đương với hầu hết các phép so sánh.

Ngoại lệ duy nhất cho quy tắc này là vị từ LIKE.Khi bên phải bên của biểu thức vị từ LIKE có giá trị có dấu cách theo sau, Máy chủ SQL không đệm hai giá trị với cùng độ dài trước khi so sánh xảy ra. Vì mục đích của định nghĩa LIKE LIKE, theo định nghĩa, là để tạo điều kiện tìm kiếm mẫu thay vì thử nghiệm bình đẳng chuỗi đơn giản, điều này không vi phạm mục của đặc tả ANSI SQL-92 được đề cập trước đó.

Dưới đây là một ví dụ nổi tiếng của tất cả các trường hợp nêu trên:

DECLARE @a VARCHAR(10) 
DECLARE @b varchar(10) 

SET @a = '1' 
SET @b = '1 ' --with trailing blank 

SELECT 1 
WHERE 
    @a = @b 
AND @a NOT LIKE @b 
AND @b LIKE @a 

Dưới đây là một số chi tiết thêm về trailing blanks and the LIKE clause.

chỉ Về:

Một chèn vào một cột có giá trị phải là duy nhất sẽ thất bại nếu bạn cung cấp một giá trị được phân biệt với các giá trị hiện tại bằng cách chỉ dấu không gian. Tất cả các chuỗi sau sẽ được coi là tương đương với một ràng buộc duy nhất, khóa chính hoặc chỉ mục duy nhất. Tương tự, nếu bạn có một bảng hiện có có dữ liệu bên dưới và cố gắng thêm một hạn chế duy nhất, nó sẽ thất bại vì các giá trị là được coi là giống hệt nhau.

PaddedColumn 
------------ 
'abc' 
'abc ' 
'abc ' 
'abc ' 

(Trích từ here.)

+2

Cám ơn các con trỏ, chàng trai. Mea culpa vì quá lười biếng với Google. Theo tôi, hành vi được xác định bởi tiêu chuẩn không trực quan. Tôi tưởng tượng rằng 9 trong số 10 nhà phát triển sẽ nói rằng 'a' và 'a' KHÔNG phải là cùng một chuỗi, nhưng tốt thôi. – Eric

Các vấn đề liên quan