Desencadenadores que omitan nulos

27/08/2004 - 15:42 por gl | Informe spam
Hola a todos:

Mi consulta es la siguiente: cómo puedo hacer para que un desencadenador que
impide inserciones si no existe ninguna clave coinciente en la tabla
principal, permita valores nulos
El trigger está armado de la siguiente forma:

CREATE TRIGGER T_tbAutorizaciones_ITrig ON dbo.tbAutorizaciones FOR INSERT
AS
SET NOCOUNT ON
IF (SELECT COUNT(*) FROM inserted) ! (SELECT COUNT(*) FROM tbAut_Estado, inserted WHERE (tbAut_Estado.CodEst inserted.Estado))
BEGIN
RAISERROR 44447 'No puede agregarse ni modificarse el registro. Las
reglas de integridad referencial requieren un registro relacionado en la
tabla ''tbAut_Estado''.'
ROLLBACK TRANSACTION
END

De modo que cuando el valor ingresado no se corresponde con uno de la tabla
principal impide la modificación o el agregado. Esto es correcto, pero lo
que yo necesito es que cuando no se ingrese valor alguno no haga nada, es
decir, admita valores nulos sin que pida un registro relacionado.

Desde ya muchas gracias,

Guido



Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.744 / Virus Database: 496 - Release Date: 24/08/2004

Preguntas similare

Leer las respuestas

#1 Maxi
27/08/2004 - 15:46 | Informe spam
Hola, una sugerencia nomas:

Yo no usaria desencadenadores para este tipo de cosas, son lentos, poco
escalables y de muy dificil mantenimiento :(

A menos que la relacion de integridad este en distintas BDD pero sino usaria
Foreign Key que hace todo lo que necesitas de y de forma super simple.

Porque no usas Foreign key? que limitacion estas teniendo para ello?


Salu2
Maxi
Buenos Aires - Argentina
Desarrollador Microsoft 3 Estrellas .NET
Nunca consideres el estudio como una obligación sino como
una oportunidad para penetrar en el bello y maravillosos
mundo del saber.
- Albert Einstein



"gl" <gil_del900*AntiSpam*@argentina.com> escribió en el mensaje
news:
Hola a todos:

Mi consulta es la siguiente: cómo puedo hacer para que un desencadenador


que
impide inserciones si no existe ninguna clave coinciente en la tabla
principal, permita valores nulos
El trigger está armado de la siguiente forma:

CREATE TRIGGER T_tbAutorizaciones_ITrig ON dbo.tbAutorizaciones FOR INSERT
AS
SET NOCOUNT ON
IF (SELECT COUNT(*) FROM inserted) !> (SELECT COUNT(*) FROM tbAut_Estado, inserted WHERE (tbAut_Estado.CodEst
inserted.Estado))
BEGIN
RAISERROR 44447 'No puede agregarse ni modificarse el registro.


Las
reglas de integridad referencial requieren un registro relacionado en la
tabla ''tbAut_Estado''.'
ROLLBACK TRANSACTION
END

De modo que cuando el valor ingresado no se corresponde con uno de la


tabla
principal impide la modificación o el agregado. Esto es correcto, pero lo
que yo necesito es que cuando no se ingrese valor alguno no haga nada, es
decir, admita valores nulos sin que pida un registro relacionado.

Desde ya muchas gracias,

Guido



Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.744 / Virus Database: 496 - Release Date: 24/08/2004







Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.740 / Virus Database: 494 - Release Date: 16/08/2004
Respuesta Responder a este mensaje
#2 Javier Loria
27/08/2004 - 16:21 | Informe spam
Hola:
Aparte de recomendarte que sigas el acertado comentario de Max respecto
a la ventaja de usar integridad referencial, podrias reexpresas el IF como:
=...
IF EXISTS (SELECT *
FROM Inserted
LEFT JOIN TbAut_Estado
ON Inserted.Estado=TbAut_Estado.CodEst
WHERE Inserted.Estado IS NOT NULL
AND TbAut_Estado.CodEst IS NULL)
BEGIN

= Esta sentencia es mas efectiva que el COUNT(*) y se lee la condicion del
Where como que no tenga el estado en Nulo y que no tenga un TbAut_Estado.
Un comentario sobre el diseno. Este tipo de esquema, aun con integridad
referencia es bien complicada por la logica de los nulos en SQL, veras que
luego las consultas se hacen extremadamente complejas porque tienen un
monton de LEFT JOIN, COALESCE (ISNULL) y CASE WHEN. Si puedes considera la
posibilidad un TbAut_Estado con un valor en CodEst que sea "imposible" y
definir en TbAutorizaciones, la columna Estado con este valor Default. Asi
los JOINS y otros funcionaran con faciliadad. Por ejemplo si CodEst es un
entero, define una fila que seria tu propia definicion de TbAut_Estado no
definido, con un valor de -1, y defines un valor predeterminado (Default) en
Estado.
Saludos,

Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda

"gl" <gil_del900*AntiSpam*@argentina.com> wrote in message
news:
Hola a todos:

Mi consulta es la siguiente: cómo puedo hacer para que un desencadenador


que
impide inserciones si no existe ninguna clave coinciente en la tabla
principal, permita valores nulos
El trigger está armado de la siguiente forma:

CREATE TRIGGER T_tbAutorizaciones_ITrig ON dbo.tbAutorizaciones FOR INSERT
AS
SET NOCOUNT ON
IF (SELECT COUNT(*) FROM inserted) !> (SELECT COUNT(*) FROM tbAut_Estado, inserted WHERE (tbAut_Estado.CodEst
inserted.Estado))
BEGIN
RAISERROR 44447 'No puede agregarse ni modificarse el registro.


Las
reglas de integridad referencial requieren un registro relacionado en la
tabla ''tbAut_Estado''.'
ROLLBACK TRANSACTION
END

De modo que cuando el valor ingresado no se corresponde con uno de la


tabla
principal impide la modificación o el agregado. Esto es correcto, pero lo
que yo necesito es que cuando no se ingrese valor alguno no haga nada, es
decir, admita valores nulos sin que pida un registro relacionado.

Desde ya muchas gracias,

Guido



Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.744 / Virus Database: 496 - Release Date: 24/08/2004


Respuesta Responder a este mensaje
#3 gl
27/08/2004 - 17:01 | Informe spam
Muchas gracias Javier, seguiré tus consejos.
Soy nuevo en esto, estoy acostumbrado al uso de bases .mdb, y saltar de
golpe a sql server es un poco traumático, por decirlo así.
Gracias de nuevo

Guido


"Javier Loria" escribió en el mensaje
news:
Hola:
Aparte de recomendarte que sigas el acertado comentario de Max


respecto
a la ventaja de usar integridad referencial, podrias reexpresas el IF


como:
=> ...
IF EXISTS (SELECT *
FROM Inserted
LEFT JOIN TbAut_Estado
ON Inserted.Estado=TbAut_Estado.CodEst
WHERE Inserted.Estado IS NOT NULL
AND TbAut_Estado.CodEst IS NULL)
BEGIN

=> Esta sentencia es mas efectiva que el COUNT(*) y se lee la condicion del
Where como que no tenga el estado en Nulo y que no tenga un TbAut_Estado.
Un comentario sobre el diseno. Este tipo de esquema, aun con


integridad
referencia es bien complicada por la logica de los nulos en SQL, veras que
luego las consultas se hacen extremadamente complejas porque tienen un
monton de LEFT JOIN, COALESCE (ISNULL) y CASE WHEN. Si puedes considera la
posibilidad un TbAut_Estado con un valor en CodEst que sea "imposible" y
definir en TbAutorizaciones, la columna Estado con este valor Default. Asi
los JOINS y otros funcionaran con faciliadad. Por ejemplo si CodEst es un
entero, define una fila que seria tu propia definicion de TbAut_Estado no
definido, con un valor de -1, y defines un valor predeterminado (Default)


en
Estado.
Saludos,

Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda

"gl" <gil_del900*AntiSpam*@argentina.com> wrote in message
news:
> Hola a todos:
>
> Mi consulta es la siguiente: cómo puedo hacer para que un desencadenador
que
> impide inserciones si no existe ninguna clave coinciente en la tabla
> principal, permita valores nulos
> El trigger está armado de la siguiente forma:
>
> CREATE TRIGGER T_tbAutorizaciones_ITrig ON dbo.tbAutorizaciones FOR


INSERT
> AS
> SET NOCOUNT ON
> IF (SELECT COUNT(*) FROM inserted) !> > (SELECT COUNT(*) FROM tbAut_Estado, inserted WHERE


(tbAut_Estado.CodEst
> > inserted.Estado))
> BEGIN
> RAISERROR 44447 'No puede agregarse ni modificarse el registro.
Las
> reglas de integridad referencial requieren un registro relacionado en la
> tabla ''tbAut_Estado''.'
> ROLLBACK TRANSACTION
> END
>
> De modo que cuando el valor ingresado no se corresponde con uno de la
tabla
> principal impide la modificación o el agregado. Esto es correcto, pero


lo
> que yo necesito es que cuando no se ingrese valor alguno no haga nada,


es
> decir, admita valores nulos sin que pida un registro relacionado.
>
> Desde ya muchas gracias,
>
> Guido
>
>
>
> Outgoing mail is certified Virus Free.
> Checked by AVG anti-virus system (http://www.grisoft.com).
> Version: 6.0.744 / Virus Database: 496 - Release Date: 24/08/2004
>
>







Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.744 / Virus Database: 496 - Release Date: 24/08/2004
Respuesta Responder a este mensaje
#4 gl
27/08/2004 - 17:14 | Informe spam
Maxi:

Primero gracias por responder. Soy nuevo en esto y me veo obligado a pasar
una base de datos de access (.mdb) a una estructura de sql server. Utilizo
para ello el asistente que provee access 2002 para este tipo de
conversiones. Funciona bien, pero a la hora de convertir las relaciones me
da dos posibilidades: o lo hago con triggers, o valiendome de la declaración
de integridad referencial. Esta última para mi seria la mejor opción, ya que
se me hace mas familiar al asemejarse al access, pero resulta que en algunas
tablas no convierte la actualizacion en cascada, ni siquiera si lo hago
desde el administrador corporativo del propio sql server 2000, argumentando
que podrian producirse multiples cambios en cascada (?). Es por ello que
recurrí a la opción de conversion con triggers, con el resultado comentado,
impide el ingreso de cualquier valor distinto a la tabla principal, incluso
los nulos.
Este último problema digamos que lo solucioné, de la siguiente forma:

CREATE TRIGGER T_tbAutorizaciones_ITrig ON dbo.tbAutorizaciones FOR INSERT
AS
SET NOCOUNT ON
IF (select estado FROM inserted)<>null and (SELECT COUNT(*) FROM inserted)! (SELECT COUNT(*) FROM tbAut_Estado, inserted WHERE (tbAut_Estado.CodEst inserted.Estado))
BEGIN
RAISERROR 44447 'No puede agregarse ni modificarse el registro. Las
reglas de integridad referencial requieren un registro relacionado en la
tabla ''tbAut_Estado''.'
ROLLBACK TRANSACTION
END

haciendo que no considere los nulos. También voy a probar la solución
propuesta por Javier en la otra respuesta que según comenta es más efectiva.

Ahora bien, según expresas vos, esto es lento y sería mejor hacerlo con
clave externa. El problema entonces se reduce a salvar la imposibilidad de
aplicar actualización en cascada, en algunos casos en los que, sinceramente,
no veo cual podria ser el problema. Me podrías dar alguna opinión al
respecto,

Reitero el agradecimiento por el interés,

Guido


"Maxi" escribió en el mensaje
news:
Hola, una sugerencia nomas:

Yo no usaria desencadenadores para este tipo de cosas, son lentos, poco
escalables y de muy dificil mantenimiento :(

A menos que la relacion de integridad este en distintas BDD pero sino


usaria
Foreign Key que hace todo lo que necesitas de y de forma super simple.

Porque no usas Foreign key? que limitacion estas teniendo para ello?


Salu2
Maxi
Buenos Aires - Argentina
Desarrollador Microsoft 3 Estrellas .NET
Nunca consideres el estudio como una obligación sino como
una oportunidad para penetrar en el bello y maravillosos
mundo del saber.
- Albert Einstein



"gl" <gil_del900*AntiSpam*@argentina.com> escribió en el mensaje
news:
> Hola a todos:
>
> Mi consulta es la siguiente: cómo puedo hacer para que un desencadenador
que
> impide inserciones si no existe ninguna clave coinciente en la tabla
> principal, permita valores nulos
> El trigger está armado de la siguiente forma:
>
> CREATE TRIGGER T_tbAutorizaciones_ITrig ON dbo.tbAutorizaciones FOR


INSERT
> AS
> SET NOCOUNT ON
> IF (SELECT COUNT(*) FROM inserted) !> > (SELECT COUNT(*) FROM tbAut_Estado, inserted WHERE


(tbAut_Estado.CodEst
> > inserted.Estado))
> BEGIN
> RAISERROR 44447 'No puede agregarse ni modificarse el registro.
Las
> reglas de integridad referencial requieren un registro relacionado en la
> tabla ''tbAut_Estado''.'
> ROLLBACK TRANSACTION
> END
>
> De modo que cuando el valor ingresado no se corresponde con uno de la
tabla
> principal impide la modificación o el agregado. Esto es correcto, pero


lo
> que yo necesito es que cuando no se ingrese valor alguno no haga nada,


es
> decir, admita valores nulos sin que pida un registro relacionado.
>
> Desde ya muchas gracias,
>
> Guido
>
>
>
> Outgoing mail is certified Virus Free.
> Checked by AVG anti-virus system (http://www.grisoft.com).
> Version: 6.0.744 / Virus Database: 496 - Release Date: 24/08/2004
>
>



Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.740 / Virus Database: 494 - Release Date: 16/08/2004







Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.744 / Virus Database: 496 - Release Date: 24/08/2004
Respuesta Responder a este mensaje
#5 Maxi
27/08/2004 - 17:17 | Informe spam
Hola, bueno te voy a dar una opinion personal

Yo no dudaria en aplicar integridad referencial para lo que buscas hacer,
pero yo en lo particular JAMAS aplico Delete o Update en cascada, esto no lo
hago porque cuando realmente necesito hacer un cambio de clave primaria
tengo un Store que lo hace y como los casos en que se cambian claves
primarias deberian ser contados con los dedos de la mano, es por ello que no
permito la actualizacion en cascada :-), el control lo hago por otro lado
como te comente :-)

Yo te recomendaria que uses integridad referencial y que no apliques los
CASCADE y luego analises bien cada cuanto y porque se cambian claves
primarias, si el sistema ha sido bien diseñado no deberias casi nunca hacer
este tipo de operatoria.

Un abrazo


Salu2
Maxi
Buenos Aires - Argentina
Desarrollador Microsoft 3 Estrellas .NET
Nunca consideres el estudio como una obligación sino como
una oportunidad para penetrar en el bello y maravillosos
mundo del saber.
- Albert Einstein



"gl" <gil_del900*AntiSpam*@argentina.com> escribió en el mensaje
news:
Maxi:

Primero gracias por responder. Soy nuevo en esto y me veo obligado a pasar
una base de datos de access (.mdb) a una estructura de sql server. Utilizo
para ello el asistente que provee access 2002 para este tipo de
conversiones. Funciona bien, pero a la hora de convertir las relaciones me
da dos posibilidades: o lo hago con triggers, o valiendome de la


declaración
de integridad referencial. Esta última para mi seria la mejor opción, ya


que
se me hace mas familiar al asemejarse al access, pero resulta que en


algunas
tablas no convierte la actualizacion en cascada, ni siquiera si lo hago
desde el administrador corporativo del propio sql server 2000,


argumentando
que podrian producirse multiples cambios en cascada (?). Es por ello que
recurrí a la opción de conversion con triggers, con el resultado


comentado,
impide el ingreso de cualquier valor distinto a la tabla principal,


incluso
los nulos.
Este último problema digamos que lo solucioné, de la siguiente forma:

CREATE TRIGGER T_tbAutorizaciones_ITrig ON dbo.tbAutorizaciones FOR INSERT
AS
SET NOCOUNT ON
IF (select estado FROM inserted)<>null and (SELECT COUNT(*) FROM


inserted)!> (SELECT COUNT(*) FROM tbAut_Estado, inserted WHERE (tbAut_Estado.CodEst
inserted.Estado))
BEGIN
RAISERROR 44447 'No puede agregarse ni modificarse el registro.


Las
reglas de integridad referencial requieren un registro relacionado en la
tabla ''tbAut_Estado''.'
ROLLBACK TRANSACTION
END

haciendo que no considere los nulos. También voy a probar la solución
propuesta por Javier en la otra respuesta que según comenta es más


efectiva.

Ahora bien, según expresas vos, esto es lento y sería mejor hacerlo con
clave externa. El problema entonces se reduce a salvar la imposibilidad de
aplicar actualización en cascada, en algunos casos en los que,


sinceramente,
no veo cual podria ser el problema. Me podrías dar alguna opinión al
respecto,

Reitero el agradecimiento por el interés,

Guido


"Maxi" escribió en el mensaje
news:
> Hola, una sugerencia nomas:
>
> Yo no usaria desencadenadores para este tipo de cosas, son lentos, poco
> escalables y de muy dificil mantenimiento :(
>
> A menos que la relacion de integridad este en distintas BDD pero sino
usaria
> Foreign Key que hace todo lo que necesitas de y de forma super simple.
>
> Porque no usas Foreign key? que limitacion estas teniendo para ello?
>
>
> Salu2
> Maxi
> Buenos Aires - Argentina
> Desarrollador Microsoft 3 Estrellas .NET
> Nunca consideres el estudio como una obligación sino como
> una oportunidad para penetrar en el bello y maravillosos
> mundo del saber.
> - Albert Einstein
>
>
>
> "gl" <gil_del900*AntiSpam*@argentina.com> escribió en el mensaje
> news:
> > Hola a todos:
> >
> > Mi consulta es la siguiente: cómo puedo hacer para que un


desencadenador
> que
> > impide inserciones si no existe ninguna clave coinciente en la tabla
> > principal, permita valores nulos
> > El trigger está armado de la siguiente forma:
> >
> > CREATE TRIGGER T_tbAutorizaciones_ITrig ON dbo.tbAutorizaciones FOR
INSERT
> > AS
> > SET NOCOUNT ON
> > IF (SELECT COUNT(*) FROM inserted) !> > > (SELECT COUNT(*) FROM tbAut_Estado, inserted WHERE
(tbAut_Estado.CodEst
> > > > inserted.Estado))
> > BEGIN
> > RAISERROR 44447 'No puede agregarse ni modificarse el


registro.
> Las
> > reglas de integridad referencial requieren un registro relacionado en


la
> > tabla ''tbAut_Estado''.'
> > ROLLBACK TRANSACTION
> > END
> >
> > De modo que cuando el valor ingresado no se corresponde con uno de la
> tabla
> > principal impide la modificación o el agregado. Esto es correcto, pero
lo
> > que yo necesito es que cuando no se ingrese valor alguno no haga nada,
es
> > decir, admita valores nulos sin que pida un registro relacionado.
> >
> > Desde ya muchas gracias,
> >
> > Guido
> >
> >
> >
> > Outgoing mail is certified Virus Free.
> > Checked by AVG anti-virus system (http://www.grisoft.com).
> > Version: 6.0.744 / Virus Database: 496 - Release Date: 24/08/2004
> >
> >
>
>
>
> Outgoing mail is certified Virus Free.
> Checked by AVG anti-virus system (http://www.grisoft.com).
> Version: 6.0.740 / Virus Database: 494 - Release Date: 16/08/2004
>
>



Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.744 / Virus Database: 496 - Release Date: 24/08/2004







Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.740 / Virus Database: 494 - Release Date: 16/08/2004
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida