Nếu bạn sử dụng SSMS (hoặc công cụ tương tự khác) để chạy mã do this tạo ra script, bạn sẽ gặp chính xác lỗi tương tự. Nó có thể chạy bình thường khi bạn chèn các dấu phân cách hàng loạt (GO
), nhưng bây giờ thì không, bạn cũng sẽ gặp phải vấn đề tương tự trong SSMS.
Mặt khác, lý do tại sao bạn không thể đặt GO
trong các tập lệnh động của bạn là do GO
không phải là một câu lệnh SQL, nó chỉ đơn thuần là một dấu phân cách được SSMS và một số công cụ khác công nhận. Có lẽ bạn đã biết về điều đó.
Dù sao, điểm của GO
là để công cụ biết rằng mã phải được chia nhỏ và các phần của nó chạy riêng lẻ . Và điều đó, riêng lẻ , là những gì bạn cũng nên làm trong mã của mình.
Vì vậy, bạn có các tùy chọn sau:
-
chèn
EXEC sp_execute @sql
ngay sau phần thả trình kích hoạt, sau đó đặt lại giá trị của@sql
để sau đó lưu trữ và chạy phần định nghĩa lần lượt; -
sử dụng hai biến,
@sql1
và@sql2
, lưu trữ phần IF EXISTS / DROP vào@sql1
, CREATE TRIGGER một thành@sql2
, sau đó chạy cả hai tập lệnh (một lần nữa, riêng biệt).
Nhưng sau đó, như bạn đã phát hiện ra, bạn sẽ phải đối mặt với một vấn đề khác:bạn không thể tạo trình kích hoạt trong cơ sở dữ liệu khác mà không chạy câu lệnh trong ngữ cảnh của cơ sở dữ liệu đó .
Bây giờ, có 2 cách cung cấp ngữ cảnh cần thiết:
1) sử dụng USE
tuyên bố;
2) chạy (các) câu lệnh dưới dạng truy vấn động bằng cách sử dụng EXEC targetdatabase..sp_executesql N'…'
.
Rõ ràng, tùy chọn đầu tiên sẽ không hoạt động ở đây:chúng tôi không thể thêm USE …
trước CREATE TRIGGER
, vì câu lệnh sau phải là câu lệnh duy nhất trong lô.
Tùy chọn thứ hai có thể được sử dụng, nhưng nó sẽ yêu cầu thêm một lớp tính năng động (không chắc đó có phải là một từ hay không). Đó là vì tên cơ sở dữ liệu là một tham số ở đây và vì vậy chúng ta cần chạy EXEC targetdatabase..sp_executesql N'…'
as một tập lệnh động và vì tập lệnh thực tế để chạy bản thân nó được coi là một tập lệnh động, do đó, nó sẽ được lồng vào nhau hai lần.
Vì vậy, trước EXEC sp_executesql @sql;
(thứ hai) thêm dòng sau:
SET @sql = N'EXEC ' + @dbname + '..sp_executesql N'''
+ REPLACE(@sql, '''', '''''') + '''';
Như bạn có thể thấy, để tích hợp nội dung của @sql
như một tập lệnh động lồng nhau đúng cách, chúng phải được đặt trong dấu ngoặc kép. Vì lý do tương tự, mọi dấu ngoặc kép in @sql
phải được nhân đôi (ví dụ:sử dụng REPLACE()
chức năng
, như trong tuyên bố trên).