RAISEERROR en Triggers y SP

31/07/2008 - 03:57 por spamgc | Informe spam
Tengo un SP que dentro de una transacción inserta un registro en una
tabla. Luego del insert se controla la variable @@error, que si es <>
a cero, hace rollback y finaliza el SP (goto fin)
Esa tabla tiene un trigger, que luego de hacer algunos cálculos,
actualiza un registro en una segunda tabla tabla.
Luego de actualizar ese el registro, el trigger pregunta por @@error,
que si es <> a cero, hace un raiserror(mensaje, 16, -1) y finaliza la
ejecucion del trigger (goto fin)
En la segunda tabla hay otro trigger, que controla algunas
condiciones, y si no se cumple lo que espera, hace un raiserror y
finaliza la ejecucion del trigger (goto fin).

El problema se da cuando el trigger de la segunda tabla detecta una
inconsistencia según sus reglas de negocio. El mensaje se devuelve a
la aplicación, ya que el SQLEXEC (es un frontend en visual fox)
detecta el error y mi aplicación se lo muestra al usuario. Pero los
datos se almacenan en el motor como si no hubiera habido ningun
error.
Es decir, el mensaje de error llega al frontend, pero el SP NO detecta
que hubo un error y continúa su ejecución.

Que me esta faltando?
La opción XACT_ABORT del SQL esta habilitada.

Muchas gracias

Preguntas similare

Leer las respuestas

#1 Alejandro Mesa
31/07/2008 - 16:27 | Informe spam
En la segunda tabla hay otro trigger, que controla algunas
condiciones, y si no se cumple lo que espera, hace un raiserror y
finaliza la ejecucion del trigger (goto fin).



Si no se cumplen las condiciones esperadas en el segundo trigger, puedes
abortar la transaccion usando "rollback transaction" antes de finalizar el
trigger, y en el procedimiento chequear si existe alguna transaccion abierta
antes de hacer el rollback usando @@trancount, para que no tengas conflictos.

Ejemplo:

create table dbo.t1 (
c1 int
)
go

create table dbo.t2 (
c1 int
)
go

create trigger tr_t1_ins on dbo.t1
for insert
as
if @@rowcount = 0 return

set nocount on

insert into dbo.t2(c1)
select c1 from inserted

if @@error <> 0
begin
if @@trancount <> 0
rollback transaction

raiserror('error insertando en trigger tr_t1_ins.', 16, 1)
return
end
go

create trigger tr_t2_ins on dbo.t2
for insert
as

if @@rowcount = 0 return

set nocount on

if exists (select * from inserted where c1 = 7)
begin
rollback transaction
raiserror('rolling back transaccion en tr_t2_ins.', 16, 1)
return
end
go

create procedure dbo.usp_p1
@c1 int
as
set xact_abort on
set nocount on

begin try
begin transaction
insert into dbo.t1(c1) values(@c1)
commit transaction
end try
begin catch
raiserror('error insertando en dbo.t1', 16, 1)

if @@trancount > 0
rollback transaction

return -1
end catch

return 0
go

exec dbo.usp_p1 1
go

select * from dbo.t1
select * from dbo.t2
go

exec dbo.usp_p1 7
go

select * from dbo.t1
select * from dbo.t2
go

drop procedure dbo.usp_p1
go

drop table dbo.t1, dbo.t2
go

Error Handling in SQL Server – a Background
http://www.sommarskog.se/error-handling-I.html

Implementing Error Handling with Stored Procedures
http://www.sommarskog.se/error-handling-II.html


AMB


"" wrote:

Tengo un SP que dentro de una transacción inserta un registro en una
tabla. Luego del insert se controla la variable @@error, que si es <>
a cero, hace rollback y finaliza el SP (goto fin)
Esa tabla tiene un trigger, que luego de hacer algunos cálculos,
actualiza un registro en una segunda tabla tabla.
Luego de actualizar ese el registro, el trigger pregunta por @@error,
que si es <> a cero, hace un raiserror(mensaje, 16, -1) y finaliza la
ejecucion del trigger (goto fin)
En la segunda tabla hay otro trigger, que controla algunas
condiciones, y si no se cumple lo que espera, hace un raiserror y
finaliza la ejecucion del trigger (goto fin).

El problema se da cuando el trigger de la segunda tabla detecta una
inconsistencia según sus reglas de negocio. El mensaje se devuelve a
la aplicación, ya que el SQLEXEC (es un frontend en visual fox)
detecta el error y mi aplicación se lo muestra al usuario. Pero los
datos se almacenan en el motor como si no hubiera habido ningun
error.
Es decir, el mensaje de error llega al frontend, pero el SP NO detecta
que hubo un error y continúa su ejecución.

Que me esta faltando?
La opción XACT_ABORT del SQL esta habilitada.

Muchas gracias

Respuesta Responder a este mensaje
#2 spamgc
31/07/2008 - 16:55 | Informe spam
Gracias Alajandro, la info y los links me sirvieron mucho.

On 31 jul, 11:27, Alejandro Mesa
wrote:
> En la segunda tabla hay otro trigger, que controla algunas
> condiciones, y si no se cumple lo que espera, hace un raiserror y
> finaliza la ejecucion del trigger (goto fin).

Si no se cumplen las condiciones esperadas en el segundo trigger, puedes
abortar la transaccion usando "rollback transaction" antes de finalizar el
trigger, y en el procedimiento chequear si existe alguna transaccion abierta
antes de hacer el rollback usando @@trancount, para que no tengas conflictos.

Ejemplo:

create table dbo.t1 (
c1 int
)
go

create table dbo.t2 (
c1 int
)
go

create trigger tr_t1_ins on dbo.t1
for insert
as
if @@rowcount = 0 return

set nocount on

insert into dbo.t2(c1)
select c1 from inserted

if @@error <> 0
begin
        if @@trancount <> 0
                rollback transaction

        raiserror('error insertando en trigger tr_t1_ins.', 16, 1)
        return
end
go

create trigger tr_t2_ins on dbo.t2
for insert
as

if @@rowcount = 0 return

set nocount on

if exists (select * from inserted where c1 = 7)
begin
        rollback transaction
        raiserror('rolling back transaccion en tr_t2_ins.', 16, 1)
        return
end
go

create procedure dbo.usp_p1
@c1 int
as
set xact_abort on
set nocount on

begin try
        begin transaction
        insert into dbo.t1(c1) values(@c1)
        commit transaction
end try
begin catch
        raiserror('error insertando en dbo.t1', 16, 1)

        if @@trancount > 0
                rollback transaction

        return -1
end catch

return 0
go

exec dbo.usp_p1 1
go

select * from dbo.t1
select * from dbo.t2
go

exec dbo.usp_p1 7
go

select * from dbo.t1
select * from dbo.t2
go

drop procedure dbo.usp_p1
go

drop table dbo.t1, dbo.t2
go

Error Handling in SQL Server – a Backgroundhttp://www.sommarskog.se/...ing-I.html

Implementing Error Handling with Stored Procedureshttp://www.sommarskog.se/...ng-II.html

AMB

"" wrote:
> Tengo un SP que dentro de una transacción inserta un registro en una
> tabla. Luego del insert se controla la variable @@error, que si es <>
> a cero, hace rollback y finaliza el SP (goto fin)
> Esa tabla tiene un trigger, que luego de hacer algunos cálculos,
> actualiza un registro en una segunda tabla tabla.
> Luego de actualizar ese el registro, el trigger pregunta por @@error,
> que si es <> a cero, hace un raiserror(mensaje, 16, -1) y finaliza la
> ejecucion del trigger (goto fin)
> En la segunda tabla hay otro trigger, que controla algunas
> condiciones, y si no se cumple lo que espera, hace un raiserror y
> finaliza la ejecucion del trigger (goto fin).

> El problema se da cuando el trigger de la segunda tabla detecta una
> inconsistencia según sus reglas de negocio. El mensaje se devuelve a
> la aplicación, ya que el SQLEXEC (es un frontend en visual fox)
> detecta el error y mi aplicación se lo muestra al usuario. Pero los
> datos se almacenan en el motor como si no hubiera habido ningun
> error.
> Es decir, el mensaje de error llega al frontend, pero el SP NO detecta
> que hubo un error y continúa su ejecución.

> Que me esta faltando?
> La opción XACT_ABORT del SQL esta habilitada.

> Muchas gracias
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida