SQL Server: Làm cách nào để tắt kích hoạt chỉ cập nhật cho phiên hiện tại của bạn?


15

Tôi đang làm việc trên SQL Server 2008 R2.

Tôi có một lợi ích bảng có trình kích hoạt SAU, CẬP NHẬT tên là tiu_benefit .

Tôi muốn viết một câu lệnh CẬP NHẬT cho bảng này để cập nhật 1 hàng nhưng tôi không muốn kích hoạt nó. Tôi biết tôi có thể tắt kích hoạt trước CẬP NHẬT và sau đó kích hoạt kích hoạt sau CẬP NHẬT:

DISABLE TRIGGER tiu_benefit ON benefit;  
GO  
UPDATE benefit SET editor = 'srh' where benefit_id = 9876
GO
ENABLE TRIGGER tiu_benefit ON benefit;  
GO  

Nhưng việc vô hiệu hóa và kích hoạt này sẽ ảnh hưởng đến tất cả người dùng đăng nhập hiện tại. Vì vậy, có khả năng một người dùng khác chạy CẬP NHẬT / CHERTN trong khi trình kích hoạt bị vô hiệu hóa bởi tập lệnh của tôi không tốt. Đó là lý do tại sao tôi chỉ muốn vô hiệu hóa và kích hoạt kích hoạt cho phiên hiện tại của tôi. Có thể không? Nếu có xin vui lòng cho biết làm thế nào.

Cảm ơn


1
Nếu bạn không thể sửa đổi kích hoạt của mình, thì câu trả lời là không.
jyao

Câu trả lời:


6

Tôi đã thực hiện một số thử nghiệm về điều này và tôi nghĩ rằng bạn sẽ ổn nếu bạn chạy quy trình của mình trong một giao dịch.

BEGIN TRANSACTION
GO

DISABLE TRIGGER tiu_benefit ON benefit;
GO

UPDATE benefit
SET editor = 'srh'
WHERE benefit_id = 9876
GO

ENABLE TRIGGER tiu_benefit ON benefit;
GO

--Decide to commit or rollback

--commit
--rollback 

Trong thử nghiệm của tôi, tôi chỉ nhấn mạnh và thực hiện các BEGIN TRANSACTIONDISABLE TRIGGERđầu tiên. Sau đó tôi mở ra một cửa sổ truy vấn mới (thứ hai) và cố gắng để chạy các câu lệnh DML khác nhau ( SELECT, INSERT, UPDATE DELETE) chống lại các bảng cơ sở. Tất cả các nỗ lực truy cập vào bảng cơ sở trong cửa sổ truy vấn thứ hai đã chờ trên các khóa được giữ bởi cửa sổ với giao dịch rõ ràng. Khi tôi đã cam kết (hoặc khôi phục) giao dịch rõ ràng của mình, cửa sổ thứ hai có thể truy cập vào bảng.


Điều này sẽ hoạt động, nhưng các khóa có thể gây ra sự cố ngoài ý muốn, tùy thuộc vào thời gian bạn giữ giao dịch mở.
CaM

@CaM - Tôi cho rằng một bản cập nhật một hàng sẽ không mất quá nhiều thời gian giả sử OP cam kết hoặc khôi phục giao dịch nhanh chóng. Hy vọng, có một chỉ số trên benefit_id:)
Scott Hodgin

thực sự thích giải pháp này vì tôi không phải thực hiện bất kỳ thay đổi nào đối với trình kích hoạt
srh 16/07/18

18

Để giải quyết vấn đề của bạn, chúng tôi phải thực hiện một cách tiếp cận theo chương trình cho vấn đề. Có hai tuyến đường bạn có thể đi đến đây. Lý do cần các cách tiếp cận này là vì bạn không thể vô hiệu hóa trình kích hoạt cho một câu lệnh cụ thể, nó chỉ có thể bị vô hiệu hóa trong toàn bộ bảng.

Tùy chọn 1: Context_Info ()

Samuel Vanga trên MS SQL Tips đã có một ví dụ tuyệt vời:

USE AdventureWorks; 
GO 
-- creating the table in AdventureWorks database 
IF OBJECT_ID('dbo.Table1') IS NOT NULL 
DROP TABLE dbo.Table1 
GO 
CREATE TABLE dbo.Table1(ID INT) 
GO 
-- Creating a trigger 
CREATE TRIGGER TR_Test ON dbo.Table1 FOR INSERT,UPDATE,DELETE 
AS 
DECLARE @Cinfo VARBINARY(128) 
SELECT @Cinfo = Context_Info() 
IF @Cinfo = 0x55555 
RETURN 
PRINT 'Trigger Executed' 
-- Actual code goes here 
-- For simplicity, I did not include any code 
GO

Bây giờ khi Samuel không muốn kích hoạt thực thi, họ sử dụng điều này:

SET Context_Info 0x55555 
INSERT dbo.Table1 VALUES(100)

Context_Info sử dụng các chế độ xem hệ thống sau để lấy thông tin về phiên hiện tại:

  • sys.dm_exec numquests

  • sys.dm_exec_simes

  • sys.sys Processes

Hệ tư tưởng ở đây là chuỗi nhị phân bạn đang đặt chỉ được hiển thị cho phiên hiện tại, do đó, khi trình kích hoạt thực thi trong phiên của bạn, nó sẽ thấy phạm vi và cài đặt biến của Context_infohàm và nó sẽ nhảy đến phần thoát của trình kích hoạt thay thế.

Tùy chọn 2: Bảng Temp

Itzik Ben-Gan có một giải pháp tuyệt vời trong cuốn sách "Bên trong Microsoft SQL Server 2008 Lập trình T-SQL: Lập trình T-SQL" cũng nằm trong cuốn sách sau này của ông T-SQL Querying . Vấn đề chính với context_infochức năng này là chi phí nhỏ trên TempDB.

Để làm hỏng sự ngạc nhiên nhưng không phá hỏng cốt truyện của những cuốn sách (tôi cảm thấy chúng đáng để mua và đọc), bạn sẽ thay đổi kích hoạt của mình.

Kích hoạt của bạn nên thực hiện kiểm tra cho một bảng tạm thời. Nếu bảng tạm thời tồn tại, kích hoạt nên biết để kết thúc và không thực hiện các hành động.

Trong câu lệnh cập nhật bạn muốn thực hiện, trước tiên hãy tạo bảng tạm thời. Nó sẽ được nhìn thấy trong cùng một giao dịch với trình kích hoạt và nó sẽ khiến trình kích hoạt bỏ qua tuyên bố của bạn.

Ví dụ về kích hoạt:

CREATE TRIGGER TRIGGERNAME ON TABLENAME for INSERT AS

IF OBJECT_ID('tempdb..#FAKETEMPTABLE') IS NOT NULL RETURN;
GO

Ví dụ về câu lệnh bắt đầu khi bạn không muốn kích hoạt chạy:

CREATE TABLE #FAKETEMPTABLE(col1 SMALLINT);

Đặt nó hoàn toàn cho ví dụ của bạn:

ALTER TRIGGER tiu_benefit ON benefit FOR 
... 
AS
...
IF OBJECT_ID('tempdb..#FAKETEMPTABLE') IS NOT NULL RETURN;
--... rest of code here
GO

CREATE TABLE #FAKETEMPTABLE(col1 SMALLINT);
UPDATE benefit SET editor = 'srh' where benefit_id = 9876;
GO

2
Tôi sẽ sử dụng context_info () thay vì bảng tạm thời trong trình kích hoạt. Nói cách khác, nếu một trình kích hoạt phát hiện bối cảnh_info trả về một giá trị cụ thể, thì trình kích hoạt sẽ hoạt động tương ứng. Bạn có thể tham khảo câu hỏi SO có liên quan tại đây: stackoverflow.com/questions/3025662/ cấp
jyao

1
Bạn cũng có thể đặt một kiểm tra tương tự như context_infosử dụng original_login()để báo cho kích hoạt không bao giờ chạy nếu một người cụ thể đang kích hoạt.
Kenneth Fisher

2

Tôi sẽ sử dụng một trong hai CONTEXT_INFOhoặc mới hơn SESSION_CONTEXT. Cả hai đều là giá trị dựa trên phiên.

Một điều cần xem xét liên quan đến tùy chọn bảng tạm thời cục bộ và thậm chí tùy chọn vô hiệu hóa / kích hoạt: cả hai đều yêu cầu một số lượng hoạt động khóa và nhật ký tran. Cả hai tùy chọn này đều làm tăng khả năng tranh chấp, ngay cả khi tối thiểu. Hai tùy chọn "bối cảnh" chỉ nên có trọng lượng nhẹ hơn / chỉ bộ nhớ.


context_info là một thuốc giảm đau, bất cứ khi nào bạn muốn chạy thay đổi dữ liệu sản xuất đều có ích, đặc biệt là vô hiệu hóa kích hoạt có thể khiến các hoạt động khác không kích hoạt kích hoạt.
Biju jose
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.