Tạo chỉ mục trên trường được tính toán: dữ liệu chuỗi hoặc nhị phân sẽ bị cắt ngắn


8

Tôi có một bảng Foovới các trường sau:

ID bigint not null identity(1,1),
SerializedValue nvarchar(max),
LongValue as TRY_CAST(SerializedValue as bigint)

Bây giờ tôi muốn tạo một chỉ mục trên LongValue, để tôi có thể dễ dàng tra cứu các giá trị nối tiếp đại diện cho các số.

create nonclustered index IX_Foo on Foo(LongValue);

Mà phát sinh lỗi sau đây với tôi:

Chuỗi hoặc dữ liệu nhị phân sẽ được rút ngắn.

Có, có dữ liệu hiện có trong SerializedValue. Nhưng những gì, cầu nguyện, có thể được cắt ngắn bằng cách tạo ra một chỉ mục trên một trường tính toán?

Câu trả lời:


8

Lỗi không phải do tạo chỉ mục. Lỗi được gây ra bởi TRY_CASTkhi các giá trị cột được tính toán được đánh giá khi tạo chỉ mục.

Nếu tôi chạy cái này:

SELECT TRY_CAST(REPLICATE(CONVERT(nvarchar(MAX), N'a'), 4001) AS bigint)

Tôi nhận được lỗi tương tự.

Các tài liệu nói (nhấn mạnh của tôi):

Nếu diễn viên thành công, TRY_CAST trả về giá trị dưới dạng data_type đã chỉ định; nếu xảy ra lỗi, null được trả về. Tuy nhiên, nếu bạn yêu cầu một chuyển đổi rõ ràng là không được phép, thì TRY_CAST không thành công với một lỗi.

Bây giờ, không rõ chính xác trong trường hợp nào nó sẽ bị lỗi (có vẻ như loại asinine đã đưa ra toàn bộ điểm của hàm, nhưng dù sao thì ...), vì vậy chúng ta có thể sửa mã bằng cách chuyển đổi các giá trị đầu vào (sử dụng một cái gì đó hợp lý cho dữ liệu trong bảng của bạn), vì không cần phải xử lý một chuỗi lớn khi nó không phù hợp với bất kỳ vấn đề nào:

SELECT TRY_CAST(LEFT(REPLICATE(CONVERT(nvarchar(MAX), N'1'), 4001), 100) AS bigint)

Điều này trả về NULLvì giá trị không hợp lệ, nhưng nó không bị lỗi.


-1

Nếu bạn có một chuỗi có giá trị quá dài, thì việc tạo chỉ mục sẽ thất bại. Tôi đã thử một chút mã kiểm tra bằng SQL Server 2012.

CREATE TABLE dbo.foo 
(ID bigint not null identity(1,1),
SerializedValue nvarchar(max),
LongValue as TRY_CAST(SerializedValue as bigint));

INSERT INTO dbo.foo (serializedvalue) VALUES(REPLICATE(' ', 4000)+'1');

CREATE INDEX GotToTry ON foo(LongValue);

DROP TABLE dbo.foo;
GO

Thử nghiệm nhanh của tôi cho thấy mã hoạt động miễn là giá trị nvarchar (tối đa) là 4000 ký tự trở xuống. (Tất nhiên, tất cả các khoảng trống không có gì ở cuối thu gọn thành không có ký tự và do đó hoạt động tốt.) Ký tự 4001 kích hoạt String or binary data would be truncatedthông báo. Vì vậy, bạn có thể kiểm tra dữ liệu của mình để biết SerializedValue dài hơn 4000 ký tự.

EDIT: Có, chuyển đổi là a BIGINT. Vấn đề không phải là BIGINT, mà là NVARCHAR(MAX). Ví dụ:

  1. Nếu một hàng chứa '111111111111111111', nó sẽ cả hai CREATE INDEXvà chuyển đổi giá trị thành BIGINT.
  2. Nếu một hàng là 0 đến 4000 '1 thì có thể CREATE INDEX, nhưng giá trị có thể là NULLdo nó tràn ra BIGINT.
  3. Nếu một hàng dài hơn 4000 ký tự, thì CREATE INDEXthất bại.

Vì vậy, có vẻ như nội dung thực tế của NVARCHAR (MAX) mới là điều quan trọng đối với CREATE INDEX.

EDIT: Jon Seigel xác định rằng TRY_CAST gây ra lỗi khi tạo chỉ mục khi chuỗi dài hơn nvarchar (4000).


2
Điều này không thực sự trả lời câu hỏi. Các chỉ số là trên một bigint. Nó sẽ không bao giờ là bất cứ điều gì khác hơn là một vấn đề lớn. Câu hỏi đặt ra là tại sao dữ liệu sẽ bị cắt ngắn khi một điểm lớn nằm trong phạm vi trợ cấp kích thước cho một chỉ mục
Mark Sinkinson

1
@MarkSinkinson Đã chỉnh sửa để cung cấp thêm chi tiết. Vấn đề là nội dung NVARCHAR (MAX).
RLF
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.