2010-01-29 34 views
6

Tôi có một số mã trong trình kích hoạt chèn sau có khả năng không thành công. Sự thất bại như vậy không quan trọng và nên không hoàn nguyên giao dịch. Làm thế nào tôi có thể bẫy lỗi bên trong kích hoạt và có phần còn lại của giao dịch thực hiện bình thường?TSQL khiến kích hoạt không âm thầm

Ví dụ bên dưới minh họa ý của tôi. Trình kích hoạt cố ý tạo ra một điều kiện lỗi với kết quả rằng chèn ban đầu ("1") không bao giờ chèn vào bảng. Try/Catch dường như không làm trò lừa. Tương tự, older stack overflow question không mang lại câu trả lời ngoại trừ "ngăn lỗi xảy ra ngay từ đầu" - điều này không phải lúc nào cũng có thể/dễ dàng.

Bất kỳ ý tưởng nào khác?

create table test 
(
    a int not null 
); 
go 

create trigger testTrigger on test 
after insert as 
begin 
    insert into test select null; 
end; 
go 

insert into test values (1); 
+1

Tại sao thử/Bắt không hoạt động? – cjk

+0

@ck: bởi vì các ràng buộc vi phạm bên trong các trigger gây ra các giao dịch. – Quassnoi

Trả lời

2

Trình kích hoạt không thể thất bại và vẫn có giao dịch chuyển tiếp. Bạn có một vài tùy chọn để đảm bảo rằng trình kích hoạt không thành công.

1 - Bạn có thể đảm bảo rằng sau khi không thất bại bằng cách sao chép logic để kiểm tra các ràng buộc và không cố gắng một hoạt động mà sẽ vi phạm những ràng buộc:

tức

INSERT INTO test WHERE val IS NOT NULL 

2 - Bạn có thể trì hoãn hành động có khả năng thất bại bằng cách sử dụng mẫu thiết kế hàng đợi nơi các hành động có thể hoặc không thể thất bại được xếp hàng đợi bằng cách enqueueing vào một bảng nơi hoạt động enqueueing không thể thất bại.

ví dụ:

INSERT INTO ACTION_QUEUE (action, parameters) VALUES ('INSERT INTO TEST', val) 
+0

Tôi sợ rằng đây sẽ là cách duy nhất. Mặc dù rất khó. Xin vui lòng xem bình luận của tôi để trả lời của Quassnoi dưới đây. – BuschnicK

+0

@BuschnicK Việc kích hoạt là một trong những thứ xâm lấn nhiều hơn bạn có thể thực hiện trong một hệ thống. Nó là một phần của lược đồ cơ sở dữ liệu để thực thi hành vi cơ sở dữ liệu và bạn đang làm điều này trong cơ sở dữ liệu của người khác. Họ có vị trí của họ, nhưng tôi không nghĩ rằng việc sử dụng này là thích hợp NẾU bạn không thể đảm bảo rằng họ cư xử tốt.Thành thật mà nói nếu bạn sử dụng kích hoạt làm cơ chế duy nhất để thay đổi, nếu trình kích hoạt thất bại, các thay đổi của bạn sẽ không được chuyển, nhưng giao dịch có thể hoàn tất và bạn sẽ mất thông báo "thay đổi" dữ liệu đồng bộ hóa lại dữ liệu của bạn một cách đáng tin cậy? –

+0

@BuschnicK Bạn sẽ tốt hơn khi xem xét một số loại thay đổi dữ liệu chụp hoặc kỹ thuật ETL khác để so sánh các thay đổi kể từ lần chụp gần nhất. –

1

Do cách trigger được thực hiện trong SQL Server, tất cả các hành vi vi phạm chế trong trigger diệt vong các giao dịch.

này cũng giống như thực hiện:

DROP TABLE test 

CREATE TABLE test 
(
     a INT NOT NULL 
) 

GO 

SET XACT_ABORT ON 
GO 

BEGIN TRANSACTION 

BEGIN TRY 
     INSERT 
     INTO test 
     SELECT NULL 
END TRY 
BEGIN CATCH 
     INSERT 
     INTO test 
     SELECT 1 
END CATCH 

mà kết quả trong một giao dịch bị tiêu diệt, ngoại trừ việc không có cách nào để vô hiệu hóa XACT_ABORT bên trong một cò.

SQL Server cũng thiếu giao dịch tự động.

Đó là một lý do khác khiến bạn nên đặt tất cả logic của mình vào các thủ tục được lưu trữ thay vì kích hoạt.

+0

thực sự bạn không có giao dịch doomed nếu bạn không sử dụng try..catch. –

+0

@ Alex: chắc chắn, thao tác chỉ bị hủy bỏ nguyên tử. Đây chỉ là để chứng minh những gì đang xảy ra. – Quassnoi

+0

Quy trình lưu trữ giúp đỡ như thế nào? Tôi nghĩ nếu bất cứ điều gì kích hoạt sẽ gọi thủ tục lưu trữ ... Để cung cấp một chút thông tin cơ bản về những gì tôi đang cố gắng lưu trữ ở đây: Chúng tôi có một nhà cung cấp hệ thống ERP và muốn nhận dữ liệu cập nhật trực tiếp từ đó là các bảng. Chúng tôi đính kèm kích hoạt vào bảng của họ, xoa bóp dữ liệu và sao chép nó vào cơ sở dữ liệu của chính chúng tôi. Chúng tôi muốn bảo đảm những yếu tố kích thích của chúng tôi sẽ không bao giờ thất bại vì điều đó sẽ gây ra các vấn đề trong hệ thống ERP ban đầu. – BuschnicK

0
  1. Bạn có thể bật tắt XACT_ABORT bên cò (sử dụng thận trọng)
  2. Bạn có thể kích hoạt gọi một thủ tục lưu trữ. (Tôi đang vật lộn với vấn đề ngược lại: Tôi muốn giao dịch bị hủy bỏ, nhưng vì logic nằm trong một SP được gọi từ kích hoạt, và không phải là kích hoạt, điều này không xảy ra.)
Các vấn đề liên quan