none
Insert into - Select ... Procesando datos por registro RRS feed

  • Pregunta

  • Hola, y gracias de antemano.
    Estoy intentando crear un script en T-sql para insertar registros de una tabla en otra similar. Mi dificultad es que hay un atributo (código) para el que en lugar de tomar el valor de la tabla origen lo que debo hacer es generarlo (obteniendo el mayor + 1 ) de ese mismo atributo en la tabla destino. Y se trata de un script que inserta miles de registros.
    Entonces, no puedo usar un
    "Insert into (campo1, campo código, ..,  campo n) Select (campo1, select max(codigo)+1, ..,  campo n)" porque hasta que no termina la transacción no están insertados los registros y siempre insertaría lo mismo, tampo una función que lo calcule por lo mismo.
     
    alguna sugerencia?
    miércoles, 10 de noviembre de 2010 22:36

Respuestas

  • La primera sugerencia es que postees l estructura de las tablas involucradas, data de ejemplo en forma de sentencia "insert", asi como el resultado esperado.

    Logicamente que para hacer esto se debera ? (hacer lock a la tabla) para que otras sesiones no puedan insertar mientras haces el insert. Aqui tienes un ejemplo, donde tenemos dos tablas y queremos insertar las filas de la tabla T2 en la tabla T1 pero queremos seguir la secuencia de la columna [c2] en T1.

    USE tempdb;
    GO
    CREATE TABLE T1 (
    c1 int NOT NULL,
    c2 int NOT NULL,
    );
    GO
    CREATE TABLE T2 (
    c1 int NOT NULL,
    c2 int NOT NULL,
    );
    GO
    INSERT INTO T1 VALUES(1, 1);
    INSERT INTO T1 VALUES(1, 2);
    INSERT INTO T1 VALUES(1, 3);
    
    INSERT INTO T1 VALUES(2, 1);
    INSERT INTO T1 VALUES(2, 2);
    GO
    INSERT INTO T2 VALUES(1, 100);
    INSERT INTO T2 VALUES(1, 101);
    INSERT INTO T2 VALUES(1, 102);
    INSERT INTO T2 VALUES(1, 103);
    
    INSERT INTO T2 VALUES(2, 200);
    INSERT INTO T2 VALUES(2, 201);
    INSERT INTO T2 VALUES(2, 202);
    INSERT INTO T2 VALUES(2, 203);
    INSERT INTO T2 VALUES(2, 204);
    INSERT INTO T2 VALUES(2, 205);
    INSERT INTO T2 VALUES(2, 206);
    INSERT INTO T2 VALUES(2, 207);
    GO
    SET XACT_ABORT ON;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    
    BEGIN TRY
      BEGIN TRANSACTION;
      
      INSERT INTO T1(c1, c2)
      SELECT
      	B.c1,
      	A.max_c2 + ROW_NUMBER() OVER(PARTITION BY B.c1 ORDER BY B.c2)
      FROM
      	(SELECT c1, MAX(c2) AS max_c2 FROM T1 GROUP BY c1) AS A
      	INNER JOIN
      	T2 AS B
      	ON A.c1 = B.c1;
      
      COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
      IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
      
      SELECT
        ERROR_NUMBER() AS e_n,
        ERROR_MESSAGE() AS e_m;
        
    END CATCH;
    GO
    SELECT *
    FROM T1
    ORDER BY c1, c2;
    GO
    DROP TABLE T1, T2;
    GO
    

    Espero te sea de ayuda.

     


    AMB

    Some guidelines for posting questions...

    miércoles, 10 de noviembre de 2010 23:36

Todas las respuestas

  • La primera sugerencia es que postees l estructura de las tablas involucradas, data de ejemplo en forma de sentencia "insert", asi como el resultado esperado.

    Logicamente que para hacer esto se debera ? (hacer lock a la tabla) para que otras sesiones no puedan insertar mientras haces el insert. Aqui tienes un ejemplo, donde tenemos dos tablas y queremos insertar las filas de la tabla T2 en la tabla T1 pero queremos seguir la secuencia de la columna [c2] en T1.

    USE tempdb;
    GO
    CREATE TABLE T1 (
    c1 int NOT NULL,
    c2 int NOT NULL,
    );
    GO
    CREATE TABLE T2 (
    c1 int NOT NULL,
    c2 int NOT NULL,
    );
    GO
    INSERT INTO T1 VALUES(1, 1);
    INSERT INTO T1 VALUES(1, 2);
    INSERT INTO T1 VALUES(1, 3);
    
    INSERT INTO T1 VALUES(2, 1);
    INSERT INTO T1 VALUES(2, 2);
    GO
    INSERT INTO T2 VALUES(1, 100);
    INSERT INTO T2 VALUES(1, 101);
    INSERT INTO T2 VALUES(1, 102);
    INSERT INTO T2 VALUES(1, 103);
    
    INSERT INTO T2 VALUES(2, 200);
    INSERT INTO T2 VALUES(2, 201);
    INSERT INTO T2 VALUES(2, 202);
    INSERT INTO T2 VALUES(2, 203);
    INSERT INTO T2 VALUES(2, 204);
    INSERT INTO T2 VALUES(2, 205);
    INSERT INTO T2 VALUES(2, 206);
    INSERT INTO T2 VALUES(2, 207);
    GO
    SET XACT_ABORT ON;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    
    BEGIN TRY
      BEGIN TRANSACTION;
      
      INSERT INTO T1(c1, c2)
      SELECT
      	B.c1,
      	A.max_c2 + ROW_NUMBER() OVER(PARTITION BY B.c1 ORDER BY B.c2)
      FROM
      	(SELECT c1, MAX(c2) AS max_c2 FROM T1 GROUP BY c1) AS A
      	INNER JOIN
      	T2 AS B
      	ON A.c1 = B.c1;
      
      COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
      IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
      
      SELECT
        ERROR_NUMBER() AS e_n,
        ERROR_MESSAGE() AS e_m;
        
    END CATCH;
    GO
    SELECT *
    FROM T1
    ORDER BY c1, c2;
    GO
    DROP TABLE T1, T2;
    GO
    

    Espero te sea de ayuda.

     


    AMB

    Some guidelines for posting questions...

    miércoles, 10 de noviembre de 2010 23:36
  • Muchas gracias, aunque hay alguna instruccion q no entiendo, voy a probarlo.
    Miguel 1000
    viernes, 12 de noviembre de 2010 6:48