Vì vậy, tôi nhận được thông báo lỗi sau từ SQL Server khi sp_SomeProc cố gắng thực thi câu lệnh sql không hợp lệ. Tôi gặp lỗi:Lỗi kích hoạt: Giao dịch hiện tại không thể được cam kết và không thể hỗ trợ các thao tác ghi vào tệp nhật ký
The current transaction cannot be committed and cannot support operations that write to the log file.
Bất kỳ ý tưởng nào về những gì tôi đang làm sai? ("Tại sao bạn làm điều này" đây chỉ là một mẫu mà tôi tạo ra để bắt chước các vấn đề vì vậy hãy không, "này có ý nghĩa quan an ninh", vv ..)
Vì vậy bàn của tôi trông giống như:
CREATE TABLE tSOMETABLE
(
RecID INT NOT NULL IDENTITY(1,1)
Val VARCHAR(20),
CONSTRAINT [PK_tSOMETABLE] PRIMARY KEY CLUSTERED
(
RecID ASC
)
)
Vì vậy, trong kích hoạt của tôi, tôi có:
CREATE TRIGGER [dbo].[TR_tSOMETABLE_INSERT]
ON [dbo].[tSOMETABLE]
FOR INSERT
AS
SET NOCOUNT ON
BEGIN
BEGIN
SELECT * INTO #temp FROM INSERTED
WHILE EXISTS (SELECT 1 FROM #temp)
BEGIN
DECLARE @RecID INT
SELECT @RecID = RecID
FROM #temp t
EXEC dbo.sp_SomeProc @EventType = 'ON INSERT', @RecID = @RecID
DELETE #temp WHERE @RecID = RecID
END
END
END
Bây giờ mã của sp_SomeProc trông giống như:
CREATE PROC sp_SomeProc
(
@EventType VARCHAR(50),
@RecID INT,
@Debug BIT = 0
)
AS
BEGIN
SET NOCOUNT ON
DECLARE @ProcTable TABLE
(
RecID INT NOT NULL IDENTITY(1,1),
Cmd VARCHAR(MAX)
)
INSERT INTO @ProcTable(Cmd)
SELECT 'EXEC sp_who'
UNION
SELECT 'EXEC sp_SomeStoredProcThatDoesntExist'
DECLARE @RecID INT
SELECT @RecID = MIN(RecID) FROM @ProcTable
WHILE @RecID IS NOT NULL
BEGIN
DECLARE @sql VARCHAR(MAX)
SELECT @sql = cmd FROM @ProcTable WHERE RecID = @RecID
IF @Debug = 1
PRINT @sql
ELSE
BEGIN
BEGIN TRY
EXEC(@sql)
END TRY
BEGIN CATCH
DECLARE @Msg VARCHAR(MAX), @ErrorNumber INT, @ErrorSeverity INT, @ErrorState int, @ErrorProcedure nvarchar(256), @ErrorLine int, @ErrorMessage nvarchar(MAX)
SELECT @Msg = 'Failed While Executing: ' + @sql
SELECT @ErrorNumber = ERROR_NUMBER(), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(), @ErrorProcedure = ERROR_PROCEDURE(), @ErrorLine = ERROR_LINE(), @ErrorMessage = ERROR_MESSAGE()
-- DO SOME MORE STUFF HERE AND THEN ...
RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState)
END CATCH
END
SELECT @RecID = MIN(RecID) FROM @ProcTable WHERE RecID > @RecID
END
END
Vì vậy, để kiểm tra tôi cố gắng:
INSERT INTO tSOMETABLE(Val)
SELECT 'Hello'
Quay lại các khái niệm cơ bản. Trình kích hoạt thực sự đang cố gắng làm gì? Tại sao bạn không thể làm điều đó như là một hoạt động dựa trên thiết lập bên trong kích hoạt bằng cách sử dụng 'chèn' thay vì hàng lặp bởi hàng đau đớn và thực hiện một thủ tục riêng biệt, phức tạp được lưu trữ cho mỗi hàng? –
Không thể, trình kích hoạt cần thực thi một số procs được lưu trữ cho mỗi hàng đang được chèn dựa trên dữ liệu đang đi vào hàng. Nó cần phải thực hiện sql động và nó không thể được thực hiện như là một hoạt động thiết lập. Tôi không kiểm soát được procs được lưu trữ mà nó thực hiện cho mỗi hàng. Trong việc thực hiện đầy đủ có một bảng quyết định sql nào sẽ chạy cho mỗi hàng INSERTED (nhưng điều đó không liên quan cho câu hỏi này) – Denis