Có cách nào để buộc Nghị quyết Tên hoãn lại ngay cả khi bảng tồn tại khi tạo thủ tục được lưu trữ không?


10

Khi tạo một thủ tục được lưu trữ trong SQL Server, bạn được phép tham khảo các bảng không tồn tại. Nhưng, nếu bảng tồn tại thì bất kỳ cột nào bạn tham chiếu trong thủ tục phải tồn tại trong bảng đó ( Độ phân giải tên hoãn lại ).

Có thể hướng dẫn SQL Server trì hoãn độ phân giải tên của tất cả các bảng được tham chiếu trong một quy trình không phân biệt chúng có tồn tại hay không? Tôi muốn giữ kiểm tra cú pháp chung, vì vậy ngay cả khi có thể, việc hack định nghĩa thủ tục được lưu trữ trong bảng hệ thống không phải là một tùy chọn.

Tôi hy vọng yêu cầu của tôi để làm điều này có vẻ hơi lạ , vì vậy đây là một số nền tảng: Tôi tự động tạo định nghĩa bảng và quy trình được lưu trữ từ một ứng dụng được viết bằng C # và tôi rất khó thay đổi mã để đặt hàng các thay đổi khi SQL cần họ Mã của tôi "đảm bảo" rằng lược đồ phù hợp trong một giao dịch, nhưng hiện tại tôi không thể đảm bảo rằng các cột trong bảng được xác định trước khi tôi xác định thủ tục được lưu trữ tham chiếu đến chúng.

Dưới đây là một ví dụ điển hình về SQL được tạo bởi C #, "minh họa" cho vấn đề tôi đang cố gắng giải quyết.

--Say this table already exists.
CREATE TABLE myTable
(
    a NVARCHAR(MAX)
)
GO

--My C# code creates something like this
BEGIN TRAN 
GO

--the stored procedure gets generated first.
CREATE PROCEDURE mySproc
AS
BEGIN
    SELECT a,b FROM myTable
END

--then the table update
ALTER TABLE myTable
    ADD b nvarchar(MAX)

COMMIT TRAN 

tốt cho tôi để sửa lỗi này trong mã C #, nhưng tôi hy vọng cho một đơn giản "ma thuật" tinh chỉnh tôi có thể kéo trong SQL. Điều này sẽ tiết kiệm rất nhiều thời gian cho tôi.


1
Bạn có thể xử lý tất cả các thay đổi lược đồ trước khi tạo / thay đổi bất kỳ thủ tục nào không? Tại sao thủ tục phải tồn tại trước khi bảng là chính xác?
Aaron Bertrand

Tôi đang theo đuổi tùy chọn đó trong mã bây giờ. Cách SQL được tạo ra khá phức tạp (đó là một ví dụ đơn giản) nhưng có vẻ như nó sẽ không nhiều như một PITA như tôi nghĩ.
Daniel James Bryars

2
Tất nhiên, bạn có thể khắc phục bằng cách nhồi các thủ tục được lưu trữ đầy SQL động - nhưng tôi không thể tưởng tượng việc tạo tập lệnh của bạn để xử lý các thay đổi lược đồ thì các thủ tục được lưu trữ sẽ rất khó khăn. Không có quá nhiều tùy chọn được đưa ra để chỉ ra cách thức giải quyết tên bị hoãn. Đề xuất duy nhất về những cuốn sách mà tôi biết, hoặc ít nhất là tôi có thể suy luận rằng họ thích giải trí, thực ra là một cách khác - làm cho nó nghiêm ngặt hơn - xem sommarskog.se/strict_checks.html ).
Aaron Bertrand

Ý tưởng tốt về SQL động. Tôi đã gặp vấn đề tương tự đối với Triggers, Index, Views, Sprocs và Function. Nhưng tôi đã thay đổi mã để nó chỉ thay đổi các Bảng, rồi Lập chỉ mục, rồi Kích hoạt, rồi chức năng, rồi quay vòng.
Daniel James Bryars

Tôi thích đề xuất của sommarskog, chắc chắn sẽ giúp tránh lỗi. Nếu họ đã thực hiện một tùy chọn Nghiêm, thì họ cũng có thể đánh giá lại tất cả các sprocs "Strict ON" khi có thay đổi bảng để xem liệu nó có phá vỡ các sprocs hiện tại hay không - rõ ràng bạn sẽ cần phải có "giao dịch logic trên DDL" sau đó có thể thay đổi Bảng và Sprocs thành một đơn vị.
Daniel James Bryars

Câu trả lời:


6

Không.

Tôi cảm thấy rất có lỗi khi chỉ gõ nó, nhưng không, thật đáng buồn. Đó là lần đầu tiên tôi nghe về trường hợp sử dụng này, và nó có ý nghĩa hoàn hảo. Tốt nhất để gửi yêu cầu cho nó trên http://connect.microsoft.com và cháu của bạn sẽ có thể làm điều đó. ;-)


5

Chỉ trong trường hợp bạn vẫn quan tâm, có một cách giải quyết tiềm năng mà bạn có thể sử dụng. Dưới đây là mã được cập nhật, giới thiệu #deferResolutionbảng tạm thời cho mỗi truy vấn trong quy trình. Vì bảng tạm thời sẽ chỉ tồn tại trong thời gian chạy, quy trình có thể biên dịch ngay cả khi các cột thích hợp chưa tồn tại myTable.

Thậm chí, bạn sẽ nhận được cùng một kế hoạch thực hiện (không tham chiếu đến #deferResolutionbảng) cho mỗi câu lệnh trong quy trình do cách trình tối ưu hóa truy vấn có thể chứng minh điều này WHERE NOT EXISTSluôn luôn được đánh giá là đúng.

Tất cả những gì đã nói, đây là một vụ hack khủng khiếp được trình bày chủ yếu vì lợi ích trí tuệ và có thể có một trường hợp cạnh mà nó bị phá vỡ. Như Aaron đề cập, bạn có thể sẽ tốt hơn khi thực hiện tất cả các thay đổi lược đồ của mình theo đúng thứ tự.

--Say this table already exists.
CREATE TABLE myTable
(
    a NVARCHAR(MAX)
)
GO

--My C# code creates something like this
BEGIN TRAN 
GO

--the sproc gets generated first.
CREATE PROCEDURE mySproc
AS
BEGIN
    CREATE TABLE #deferResolution (dummy INT NOT NULL)
    SELECT a,b FROM myTable WHERE NOT EXISTS (SELECT * FROM #deferResolution WHERE 0=1)
END

--then the table update
ALTER TABLE myTable
    ADD b nvarchar(MAX)

COMMIT TRAN 
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.