Dostaję następujący komunikat o błędzie z SQL Server, gdy sp_SomeProc spróbuje wykonać niepoprawną instrukcję sql. I pojawia się błąd:Błąd wyzwalacza: Bieżąca transakcja nie może zostać zatwierdzona i nie obsługuje operacji zapisujących do pliku dziennika.
The current transaction cannot be committed and cannot support operations that write to the log file.
jakieś pomysły na to, co robię źle? („Dlaczego to robisz” to tylko próbka że stworzony, aby naśladować problem, więc proszę nie „to ma wpływ na bezpieczeństwo”, itd ..)
Więc moja tabela wygląda następująco:
CREATE TABLE tSOMETABLE
(
RecID INT NOT NULL IDENTITY(1,1)
Val VARCHAR(20),
CONSTRAINT [PK_tSOMETABLE] PRIMARY KEY CLUSTERED
(
RecID ASC
)
)
Więc w moim spuście mam:
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
teraz kod sp_SomeProc wygląda następująco:
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
Więc przetestować Staram:
INSERT INTO tSOMETABLE(Val)
SELECT 'Hello'
Wracaj do podstaw. Jaki wyzwalacz faktycznie próbuje wykonać? Dlaczego nie możesz tego zrobić jako operacji opartej na zestawie wewnątrz wyzwalacza za pomocą 'wstawionego' zamiast pętli wiersza przez bolesny wiersz i wykonując oddzielną, skomplikowaną procedurę przechowywaną dla każdego wiersza? –
Nie można, wyzwalacz musi wykonać niektóre przechowywane procs dla każdego wstawianego wiersza na podstawie danych, które trafiają do wiersza. Musi uruchamiać sql dynamicznie i nie można tego zrobić jako operacji set. Nie mam kontroli nad przechowywanymi procami, które wykonuje dla każdego wiersza. W pełnej implementacji znajduje się tabela, która decyduje, który sql uruchomić dla każdego wiersza INSERTED (ale to nie ma znaczenia dla tego pytania) – Denis