Làm thế nào để đặt tên ràng buộc hàm biến bảng duy nhất?


7

Tôi đang đổi tên một số ràng buộc duy nhất để phù hợp với quy ước đặt tên đối tượng cơ sở dữ liệu của chúng tôi. Thật kỳ lạ, có một số hàm có giá trị bảng nhiều dòng mà bảng trả về có các ràng buộc duy nhất như sau:

CREATE FUNCTION [dbo].[fn_name] (...)
RETURNS @Result 
TABLE
(
    ID BIGINT PRIMARY KEY,
    ...
    RowNum BIGINT UNIQUE 
)
BEGIN
    ...
    RETURN
END
GO

Tôi đã cố gắng đặt tên như thế này, nhưng không hoạt động:

CREATE FUNCTION [dbo].[fn_name] (...)
RETURNS @Result 
TABLE
(
    ID BIGINT PRIMARY KEY,
    ...
    RowNum BIGINT
    ,CONSTRAINT UC_fn_name_RowNum UNIQUE([RowNum])  
)
BEGIN
    ...
    RETURN
END
GO

Có thể đặt tên của một ràng buộc duy nhất khi nó là một phần của định nghĩa hàm biến bảng không?

Câu trả lời:


8

Biến bảng, cho dù được tạo ra từ một DECLAREhoặc từ một RETURNStrong một CREATE FUNCTIONtuyên bố, cũng như User-Defined Table loại (UDTTs), không cho phép hạn chế được đặt tên. Theo trang MSDN cho TẠO CHỨC NĂNG :

Đối số
...
        <cột_constraint> :: = và <table_constraint> :: =
        ... Các ràng buộc được đặt tên không được phép.

Một ngoại lệ "đã nêu" cho quy tắc này được tìm thấy trên trang MSDN cho DECLARE @local_variable mà trạng thái (theo giải thích của DEFAULT ):

Để duy trì khả năng tương thích với các phiên bản SQL Server trước đó, tên ràng buộc có thể được gán cho DEFAULT.

Tuy nhiên, có vẻ như đây là một lỗi với tài liệu vì tôi không thể gán tên cho ràng buộc DEFAULT, không có mô tả về cú pháp để thực hiện điều này và không có ví dụ nào về việc này trong tài liệu (tôi đã xem xa như SQL Server 2000).

Khi nói đến Bảng tạm thời, vấn đề sẽ rõ ràng hơn một chút: nếu bạn đặt tên rõ ràng cho bất kỳ ràng buộc nào, điều đó sẽ không cho phép mã chạy trong hai phiên khác nhau cùng một lúc. Các ràng buộc là các đối tượng (không giống như Index) và cần có các tên duy nhất trong cùng một lược đồ. Do đó, nếu một số mã tạo Bảng tạm thời cục bộ có các ràng buộc được đặt tên, thì nếu hai phiên chạy mã đó cùng một lúc, phiên thứ hai sẽ gặp lỗi khi tạo Bảng tạm thời do xung đột tên (xảy ra trong tempdb, nơi Bảng tạm thời tồn tại). Ví dụ: chạy các mục sau trong một tab truy vấn trong SSMS:

CREATE TABLE #Session1 (Col1 INT NOT NULL CONSTRAINT [UQ_DifferentSession] UNIQUE);

Và trong tab truy vấn khác, hãy chạy như sau:

CREATE TABLE #Session2 (Col1 INT NOT NULL CONSTRAINT [UQ_DifferentSession] UNIQUE);

Ngay cả với các Bảng tạm thời có các tên khác nhau ngoài các Bảng tạm thời cục bộ được tạo trong các phiên khác nhau, bạn vẫn sẽ nhận được lỗi sau:

Msg 2714, Cấp 16, Trạng thái 5, Dòng 1
Đã có một đối tượng có tên 'UQ_DifferentSession' trong cơ sở dữ liệu.
Msg 1750, Cấp 16, Trạng thái 0, Dòng 1
Không thể tạo ràng buộc. Xem các lỗi trước.

Tương tự như Bảng tạm thời, Biến bảng cũng không có bất kỳ định nghĩa nào cho đến khi chúng được "khai báo" và sau đó định nghĩa đó chỉ nằm trong tempdb. Nhưng chúng tôi không thể kiểm tra các xung đột tên trên Biến Bảng vì bạn không thể đặt tên cho các ràng buộc của chúng.

Mặt khác, các bảng được trả về trong TVF đa câu lệnh và Các loại bảng do người dùng xác định, mặt khác, tồn tại khác một chút so với các Bảng tạm thời ở chỗ chúng lưu trữ định nghĩa của chúng trong cơ sở dữ liệu nơi chúng tồn tại. Nhưng siêu dữ liệu họ lưu trữ trong cơ sở dữ liệu cục bộ của họ không bao giờ thực sự được sử dụng để lưu trữ dữ liệu; dữ liệu meta của chúng chỉ được sử dụng làm mẫu cho những gì sẽ được tạo (khi cần) trong tempdb. Và khi "mẫu" dữ liệu meta đó được sử dụng, các đối tượng được đặt tên trong tempdb(Khóa chính, ràng buộc duy nhất, ràng buộc mặc định và ràng buộc kiểm tra) có được các tên được tạo động dưới dạng UQ__#BC4FB52__A259EE56FAB8BB6F.


Về mong muốn đặt tên cho các ràng buộc để phù hợp với quy ước đặt tên (như đã nêu trong một nhận xét về Câu hỏi):

Mặc dù nó sẽ không ảnh hưởng gì đến việc sử dụng sp_rename(như được chỉ ra trong câu trả lời của @ Peter ), nó sẽ chỉ là một thay đổi bề ngoài. Một trong những lý do chính để có một quy ước đặt tên là để bảo trì, do đó, nếu bạn cần ALTERhoặc DROPđối tượng sau này, bạn sẽ không cần phải viết các truy vấn để khám phá những gì ở đó và sau đó ghép nó thành Dynamic SQL. Nhưng mối quan tâm đó là không liên quan ở đây vì không có cách nào để ALTERhoặc DROPhọ anyway.

Ngoài ra, bất kỳ thay đổi tên nào được thực hiện thông qua sp_renamesẽ tồn tại trong thời gian ngắn vì mọi thứ ALTER FUNCTIONsẽ giảm và tạo lại các ràng buộc và do đó cung cấp cho chúng các tên đối tượng mới được tạo. Sức mạnh này có thể bị xử lý theo chương trình với một DDL trigger mà chụp CREATE FUNCTION, ALTER FUNCTIONCREATE TYPEbáo cáo, nhưng kết quả cuối cùng của nỗ lực đó sẽ không thể là cuộc sống của bạn là bất kỳ dễ dàng hơn ;-). Nó sẽ chỉ được rằng cách chọn từ sys.objects, sys.indexessys.key_constraintsngoại hình "sạch".

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.