Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

lỗi sql động:'CREATE TRIGGER' phải là câu lệnh đầu tiên trong lô truy vấn

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@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).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hoàn nguyên giao dịch Entity Framework 6

  2. Cách DENSE_RANK () hoạt động trong SQL Server

  3. Máy chủ Sql cập nhật nhiều cột từ một bảng khác

  4. Truyền tham số chuỗi xml vào thủ tục được lưu trữ trên SQL Server

  5. Dự án cơ sở dữ liệu để thả cơ sở dữ liệu trước khi triển khai?