none
VALIDAR que el padre de un producto no tenga otro padre RRS feed

  • Pregunta

  • Necesito validar que mi campo PRPROD (padre) pueda tener hijos (PROD) pero que PRPRDO no pueda tener un padre 

    espero y me explique 

    miércoles, 11 de septiembre de 2019 23:03

Respuestas

  • Hola Valentín Alexis:

    Una opción diferente del trigger, es insertar mediante un procedimiento almacenado.

    Te pongo el ejemplo completo, ya que sobre tu tabla he reducido el número de campos para hacerlo más simple.

    CREATE TABLE [dbo].[PRODUCTO](
    [CIA] [char](2) NOT NULL,
    [PROD] [varchar](10) NOT NULL,
    [NOMPROD] [varchar](45) NOT NULL,
    [PRPROD] [varchar](10) NOT NULL,
    [PCPROD] [varchar](10) NOT NULL,
     CONSTRAINT [PK_PRODUCTO] PRIMARY KEY CLUSTERED 
    (
    [CIA] ASC,
    [PROD] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = ON, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
    ) ON [PRIMARY]
    
    GO
    
    
    insert into dbo.PRODUCTO (CIA, PROD, NOMPROD, PRPROD, PCPROD)
    VALUES
    ('A','3451'  ,'PRODUCT A','3451'  ,'OTRO'),
    ('A','141529','PRODUCT B','141529','OTRO'),
    ('A','970012','PRODUCT C','970012','OTRO'),
    ('A','970067','PRODUCT D','970012','OTRO'),
    ('A','970074','PRODUCT E','970012','OTRO'),
    ('A','970085','PRODUCT F','3451'  ,'OTRO'),
    ('A','970098','PRODUCT G','141529','OTRO');
    
    GO
    

    Ahora el escenario es el que tú has plasmado, pero como comento, un poco más corto.

    Una posible solución.

    CREATE PROCEDURE SP_INSERTAR_PRODUCTO (
      @CIA     [char](2)
    , @PROD	 [varchar](10)
    , @NOMPROD [varchar](45)
    , @PRPROD	 [varchar](10) 
    , @PCPROD	 [varchar](10) 
    )
    AS
    BEGIN
        IF (EXISTS(
    	   SELECT * FROM DBO.PRODUCTO WHERE PRPROD = @PROD
    	   ))
        BEGIN
    	   RAISERROR(N'NO SE PUEDE INSERTAR UN REGISTRO QUE YA TIENE PADRE', 10, 1);
    	  
        END
        ELSE
        BEGIN
    	   INSERT INTO dbo.PRODUCTO (CIA, PROD, NOMPROD, PRPROD, PCPROD)
    	   VALUES
    	   (@CIA,@PROD, @NOMPROD, @PRPROD, @PCPROD);
        END
    
    END
    GO

    Evaluamos la existencia o no de lo solicitado.

    EXEC SP_INSERTAR_PRODUCTO 
      @CIA     ='BA'
    , @PROD	 ='3451'
    , @NOMPROD ='AAA'
    , @PRPROD	 ='970081'
    , @PCPROD	 ='CCC';

    Salida

    jueves, 12 de septiembre de 2019 19:55
  • Hasta donde yo sé, no se puede conseguir con un simple Constraint. Si necesitas controlar este tipo de integridad de datos en lado servidor, me temo que la única solución sería escribir un trigger (con los inconvenientes que ello conlleva) y dentro del trigger validarlo escribiendo una consulta que busque si existe ese "padre".

    La otra alternativa sería controlarlo desde lado cliente, es decir, hacer una búsqueda de "padres del padre" antes de insertar un nuevo registro, y comprobar que no devuelve nada.

    jueves, 12 de septiembre de 2019 6:42
  • Hola Valentín Alexis:

    El procedure ya atiende los requisitos que solicita.

    En el mismo, se evalúa que el registro que viene en la variable PROD no sea padre. Si es padre, no se puede insertar.

    Es posible, que en RAISERROR el mensaje no sea el que quieres, pero puedes cambiarlo por el texto que te parezca oportuno.

    Inserto un hijo en 3451

    Intento insertar 3451 como hijo, y con otro padre.

    martes, 17 de septiembre de 2019 18:11
  • Gracias 

    Soy nuevo en esto como podría crear ese trigger que permita hacer lo sig 

    PROD(HIJO)

    PRPROD(PADRE)

    3451

    3451

    141529

    141529

    970012

    970012

    970067

    970012

    970074

    970012

    970085

    3451

    970098

    141529

    3451

    970081

    No permita que 3451 que es padre tenga otro padre

    espero y me explique 


    jueves, 12 de septiembre de 2019 15:46
  • Hola Valentin Alexis:

    Prueba a añadir la siguiente condición al procedure.

    CREATE PROCEDURE SP_INSERTAR_PRODUCTO (
      @CIA     [char](2)
    , @PROD	 [varchar](10)
    , @NOMPROD [varchar](45)
    , @PRPROD	 [varchar](10) 
    , @PCPROD	 [varchar](10) 
    )
    AS
    BEGIN
        
        IF ((EXISTS(SELECT * FROM DBO.PRODUCTO WHERE PRPROD = @PROD)) AND @PROD <> @PRPROD)
        BEGIN
    	   RAISERROR(N'NO SE PUEDE INSERTAR UN REGISTRO QUE YA TIENE PADRE', 10, 1);
    	  
        END
        ELSE
        BEGIN
    	   INSERT INTO dbo.PRODUCTO (CIA, PROD, NOMPROD, PRPROD, PCPROD)
    	   VALUES
    	   (@CIA,@PROD, @NOMPROD, @PRPROD, @PCPROD);
        END
    
    END
    GO
    Ya comentas

    miércoles, 18 de septiembre de 2019 5:02

Todas las respuestas

  • Hola Valentin Alexis:

    Tienes que darnos el modelo de tabla que estas utilizando para poder ayudarte con un poco de coherencia.

    Si utilizas el Management Studio, desde el explorador de objetos, expandes la base de datos, y expandes tablas, y con la tabla seleccionada, con el botón derecho del ratón,  Generar script de tabla en nueva ventana del explorador del editor de objetos.

    jueves, 12 de septiembre de 2019 6:42
  • Hasta donde yo sé, no se puede conseguir con un simple Constraint. Si necesitas controlar este tipo de integridad de datos en lado servidor, me temo que la única solución sería escribir un trigger (con los inconvenientes que ello conlleva) y dentro del trigger validarlo escribiendo una consulta que busque si existe ese "padre".

    La otra alternativa sería controlarlo desde lado cliente, es decir, hacer una búsqueda de "padres del padre" antes de insertar un nuevo registro, y comprobar que no devuelve nada.

    jueves, 12 de septiembre de 2019 6:42
  • CREATE TABLE [dbo].[PRODUCTO](
    [CIA] [char](2) NOT NULL,
    [PROD] [varchar](10) NOT NULL,
    [NOMPROD] [varchar](45) NOT NULL,
    [LINEA] [char](3) NOT NULL,
    [MARCA] [char](3) NOT NULL,
    [CAT] [char](1) NOT NULL,
    [SCAT] [char](2) NOT NULL,
    [PRES] [char](3) NULL,
    [TPROD] [char](1) NULL,
    [TUNID] [char](1) NULL,
    [CONTENIDO] [numeric](5, 1) NULL,
    [ORIGEN] [char](1) NULL,
    [INDLISTA] [char](1) NULL,
    [INDDESCONT] [char](1) NULL,
    [INDESTU] [char](1) NULL,
    [TOTPORC] [numeric](6, 2) NULL,
    [TOTUNID] [numeric](9, 4) NOT NULL,
    [FECHAALTA] [datetime] NULL,
    [USRALTA] [char](3) NULL,
    [NVOCAT] [char](1) NULL,
    [NVOSCAT] [char](2) NULL,
    [MESULTVTA] [varchar](6) NULL,
    [FECHAREV] [datetime] NULL,
    [USRREV] [char](3) NULL,
    [INDREV] [char](1) NOT NULL,
    [PRCIA] [char](2) NOT NULL,
    [PRPROD] [varchar](10) NOT NULL,
    [PCCIA] [char](2) NOT NULL,
    [PCPROD] [varchar](10) NOT NULL,
    [NOMPRODANT] [varchar](45) NOT NULL,
     CONSTRAINT [PK_PRODUCTO] PRIMARY KEY CLUSTERED 
    (
    [CIA] ASC,
    [PROD] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = ON, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
    ) ON [PRIMARY]

    GO

    ALTER TABLE [dbo].[PRODUCTO] ADD  CONSTRAINT [DF_PRODUCTO_TOTUNID]  DEFAULT ((0.0000)) FOR [TOTUNID]
    GO
    jueves, 12 de septiembre de 2019 14:28
  • Gracias 

    Soy nuevo en esto como podría crear ese trigger que permita hacer lo sig 

    PROD(HIJO)

    PRPROD(PADRE)

    3451

    3451

    141529

    141529

    970012

    970012

    970067

    970012

    970074

    970012

    970085

    3451

    970098

    141529

    3451

    970081

    No permita que 3451 que es padre tenga otro padre

    espero y me explique 


    jueves, 12 de septiembre de 2019 15:46
  • Hola Valentín Alexis:

    Una opción diferente del trigger, es insertar mediante un procedimiento almacenado.

    Te pongo el ejemplo completo, ya que sobre tu tabla he reducido el número de campos para hacerlo más simple.

    CREATE TABLE [dbo].[PRODUCTO](
    [CIA] [char](2) NOT NULL,
    [PROD] [varchar](10) NOT NULL,
    [NOMPROD] [varchar](45) NOT NULL,
    [PRPROD] [varchar](10) NOT NULL,
    [PCPROD] [varchar](10) NOT NULL,
     CONSTRAINT [PK_PRODUCTO] PRIMARY KEY CLUSTERED 
    (
    [CIA] ASC,
    [PROD] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = ON, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
    ) ON [PRIMARY]
    
    GO
    
    
    insert into dbo.PRODUCTO (CIA, PROD, NOMPROD, PRPROD, PCPROD)
    VALUES
    ('A','3451'  ,'PRODUCT A','3451'  ,'OTRO'),
    ('A','141529','PRODUCT B','141529','OTRO'),
    ('A','970012','PRODUCT C','970012','OTRO'),
    ('A','970067','PRODUCT D','970012','OTRO'),
    ('A','970074','PRODUCT E','970012','OTRO'),
    ('A','970085','PRODUCT F','3451'  ,'OTRO'),
    ('A','970098','PRODUCT G','141529','OTRO');
    
    GO
    

    Ahora el escenario es el que tú has plasmado, pero como comento, un poco más corto.

    Una posible solución.

    CREATE PROCEDURE SP_INSERTAR_PRODUCTO (
      @CIA     [char](2)
    , @PROD	 [varchar](10)
    , @NOMPROD [varchar](45)
    , @PRPROD	 [varchar](10) 
    , @PCPROD	 [varchar](10) 
    )
    AS
    BEGIN
        IF (EXISTS(
    	   SELECT * FROM DBO.PRODUCTO WHERE PRPROD = @PROD
    	   ))
        BEGIN
    	   RAISERROR(N'NO SE PUEDE INSERTAR UN REGISTRO QUE YA TIENE PADRE', 10, 1);
    	  
        END
        ELSE
        BEGIN
    	   INSERT INTO dbo.PRODUCTO (CIA, PROD, NOMPROD, PRPROD, PCPROD)
    	   VALUES
    	   (@CIA,@PROD, @NOMPROD, @PRPROD, @PCPROD);
        END
    
    END
    GO

    Evaluamos la existencia o no de lo solicitado.

    EXEC SP_INSERTAR_PRODUCTO 
      @CIA     ='BA'
    , @PROD	 ='3451'
    , @NOMPROD ='AAA'
    , @PRPROD	 ='970081'
    , @PCPROD	 ='CCC';

    Salida

    jueves, 12 de septiembre de 2019 19:55
  • es que lo que necesito es que al insertar un nuevo registro verifique si es padre y que no tenga un padre pero que si me deje insertar si es hijo 
    viernes, 13 de septiembre de 2019 16:07
  • El procedimiento cumple con lo explicado en el ejemplo. Puedes completar mas casos como el que has escrito en rojo.
    viernes, 13 de septiembre de 2019 18:20
  • PROD(HIJO)

    PRPROD(PADRE)

    3451

    3451

    3451 ESTE CODIGO YA ES PADRE COMO ES PADRE PUEDE TENER HIJOS ‘970085’DIFERENTES Y TAMBIEN PUEDE TENER A EL MISMO COMO HIJO ‘3451 

    141529

    3451 

    970012

    970012

    970067

    970012

    970074

    970012

    970085

    3451

    970098

    141530

    3451

    970081

    PERO COMO ‘3451’ YA ES PADRE NO PUEDE TENER UN PADRE DIFERENTE ‘970081


    martes, 17 de septiembre de 2019 14:42
  • Hola Valentín Alexis:

    El procedure ya atiende los requisitos que solicita.

    En el mismo, se evalúa que el registro que viene en la variable PROD no sea padre. Si es padre, no se puede insertar.

    Es posible, que en RAISERROR el mensaje no sea el que quieres, pero puedes cambiarlo por el texto que te parezca oportuno.

    Inserto un hijo en 3451

    Intento insertar 3451 como hijo, y con otro padre.

    martes, 17 de septiembre de 2019 18:11
  • SI ESTA BIEN LO QUE ME A PASADO AHORA AQUÍ EL PROBLEMA ES QUE

    EJEMPLO TENGO 3451 COMO PADRE POR ENDE NO PUDE TENER OTRO PADRE ASTA ESTA PARTE ESTAMOS BIEN. AHORA 3451 PUEDE SER HIJO DE 3451 ESO ES LO QUE ME FALTA  QUE VALIDE SI ES PADRE PERO QUE SI ES EL MISMO PRODUCTO PUEDA SER SU HIJO IGUAL ESTA RARO PERO ASÍ ME LO PIDIERON Y NO SE COMO HACER ESA VALIDACIÓN 

    martes, 17 de septiembre de 2019 19:08
  • Hola Valentin Alexis:

    Prueba a añadir la siguiente condición al procedure.

    CREATE PROCEDURE SP_INSERTAR_PRODUCTO (
      @CIA     [char](2)
    , @PROD	 [varchar](10)
    , @NOMPROD [varchar](45)
    , @PRPROD	 [varchar](10) 
    , @PCPROD	 [varchar](10) 
    )
    AS
    BEGIN
        
        IF ((EXISTS(SELECT * FROM DBO.PRODUCTO WHERE PRPROD = @PROD)) AND @PROD <> @PRPROD)
        BEGIN
    	   RAISERROR(N'NO SE PUEDE INSERTAR UN REGISTRO QUE YA TIENE PADRE', 10, 1);
    	  
        END
        ELSE
        BEGIN
    	   INSERT INTO dbo.PRODUCTO (CIA, PROD, NOMPROD, PRPROD, PCPROD)
    	   VALUES
    	   (@CIA,@PROD, @NOMPROD, @PRPROD, @PCPROD);
        END
    
    END
    GO
    Ya comentas

    miércoles, 18 de septiembre de 2019 5:02