none
definición para un dato consecutivo RRS feed

  • Pregunta

  • Buenas, en la siguiente tabla 

    CREATE TABLE CamposDatos
    (
    	CampoDatoConsecutivo int NULL,	-- Consecutivo por registro del campo.
    	CamposDatosValor varchar(max) NULL,	-- Valor cualquiere, ejem: '90' o 'Nomina'
    	IdCampo int NULL
    )

    el campo "CampoDatoConsecutivo" lo tengo q definir que se le vaya sumando + 1, respecto a lo que se reciba en IdCampo.

    Por ejemplo, suponiendo que en Id campo el solo se inserten 3 valorees, o sea, 1 2 y 3.

    Por lo que para el primer registro 1 de idCampo, CampoDatoConsecutivo seria 1. si vuelvo a insertar en idCampo 1, en CampoDatoConsecutivo le sumaria + 1, por lo que ya seria 2.

    Si inserto ahora el valor de 2 en idCampo, CampoDatoConsecutivo seria 1. si vuelvo a insertar en idCampo el valor de 2, en CampoDatoConsecutivo le sumaria + 1, por lo que ya seria 2. y si vuelvo a insertar el valor de 2 en idCampo, CampoDatoConsecutivo ahora seria 3, pues le estoy sumando 1.

    Mi problema esque no se como hacer para que tome el valor de idCampo que le corresponde a la hora de tratar de definir CampoDatoConsecutivo.

    esto es lo q llevo:

    declare CampoDatoConsecutivo int 
    	set @CampoDatoConsecutivo = (select max(CampoDatoConsecutivo) from CamposDatos 
    	

    me imagino tiene que ser un where donde involucre a idCampo, pero no se de que forma hacer para que diferencia entre si su valor es 1,2 o 3 y ya de ahí CampoDatoConsecutivo haga su incremento + 1

    OJO: No creo que row_number() funcione ni tampoco sequence, pues ya los investigue y no veo forma en poder aplicarlo aquí.

    Agradecería su ayuda!


    • Editado BrendaCap viernes, 30 de septiembre de 2022 17:13
    viernes, 30 de septiembre de 2022 17:12

Respuestas

  • Hola BrendaCap:

    En el planteamiento hay un pequeño problema, que es pensar que las inserciones son una sola fila, ya que pueden venir más de una en cada. Tienes que pensarlo como un conjunto de inserciones.

    Además si planteas la solución para una sola sentencia insert, y luego se inserta de otra manera (por ejemplo desde un procedure, o un bulkcopy, o una sentencia merge), te fallaría todo.

    Vamos a buscar una solución adecuada para todas las posibles implementaciones.

    Para esto vamos a usar un trigger instead of insert, que se encargará de llevar la inserción final en la tabla.

    Create trigger dbo.CamposDatos_TrInsteadOfInsert
    on dbo.CamposDatos
    Instead of insert
    As
    Begin
    
    	Set Nocount on;
    	With act As
    	(
    		Select MAX(CampoDatoConsecutivo) as consecutivo
    		, idCampo 
    		From dbo.CamposDatos 
    		GROUP BY idCampo
    	), insertado as
    	(
    		Select 
    			CamposDatosValor
    			, idCampo
    			, ROW_NUMBER() over (PARTITION BY idCampo
    			order by (Select null)) as rn
    			From inserted
    	)
    	Insert into dbo.CamposDatos
    	(CampoDatoConsecutivo, CamposDatosValor, IdCampo)
    	Select ISNULL(act.consecutivo,0)+insertado.rn
    		, insertado.CamposDatosValor
    		, insertado.IdCampo
    	From insertado left join act on insertado.IdCampo = act.IdCampo;
    End
    GO

    Si observas el trigger, en el conjunto act se encarga de obtener el max actual de cada idCampo

    En el conjunto insertado, sobre lo que viene en la sentencia, se encarga de numerarlos particionando por idCampo

    E inserta los registros, pero usando lo que existía (caso de haberlo), mas la numeración, para cada idCampo y valor que venga..

    Puesta en práctica.

    INSERT INTO dbo.CamposDatos
    	(CampoDatoConsecutivo
    	,CamposDatosValor
    	,IdCampo
    	)
    Values
    (null,'90',1);


    El primero del grupo idCampo=1 lo numera como 1

    Inserto otro del mismo grupo idCampo=1

    INSERT INTO dbo.CamposDatos
    	(CampoDatoConsecutivo
    	,CamposDatosValor
    	,IdCampo
    	)
    Values
    (null,'Nómina',1);


    Ahora inserto en un grupo idCampo=2

    INSERT INTO dbo.CamposDatos
    	(CampoDatoConsecutivo
    	,CamposDatosValor
    	,IdCampo
    	)
    Values
    (null,'EjemploGrupo2',2);


    Pero como te comentaba, si la sentencia de inserción, tiene múltiples filas, también es válido.

    INSERT INTO dbo.CamposDatos
    	(CampoDatoConsecutivo
    	,CamposDatosValor
    	,IdCampo
    	)
    Values
     (1,'monedas',1)
    ,(1,'camisas',2)
    ,(null,'500',1)
    ,(1,'71',3)
    ,(1,'pantalón',3)
    ,(1,'otro',4);

    Claramente el campoDatoConsecutivo de la sentencia de inserción, lo obvia.

    Trigger instead of

    https://javifer2.wordpress.com/2020/05/03/trigger-que-es-como-se-hace-y-como-funciona-instead-of/

    Cte correlativo

    https://javifer2.wordpress.com/2018/12/18/with-cte-tablas-de-expresion-comun-2-correlativos/

    Row number

    https://javifer2.wordpress.com/2019/11/11/row-number-numerar-filas/

    • Marcado como respuesta BrendaCap sábado, 1 de octubre de 2022 22:54
    sábado, 1 de octubre de 2022 6:20