it-swarm-eu.dev

Přesouvání řádků z jedné tabulky do druhé

V rámci procesu archivace přesouvám záznamy z jedné databáze do druhé. Chci zkopírovat řádky do cílové tabulky a poté odstranit stejné řádky ze zdrojové tabulky.

Moje otázka zní: Jaký je nejúčinnější způsob, jak zkontrolovat, zda byl první vklad úspěšný před odstraněním řádků.

Moje myšlenka je taková, ale mám pocit, že existuje lepší způsob:

@num_records=select count(ID) from Source_Table where (criteria for eligible rows)

insert * into Destination_Table where (criteria for eligible rows)

if ((select count(ID) from Destination_Table where (criteria) )[email protected])

delete * from Source_Table where (criteria)

Je lepší/možné jej kombinovat s funkcí RAISERROR? Děkuju!

9
Dina

Doporučuji TRY/CATCH syntaxi spolu s explicitními transakcemi. Můj předpoklad pro toto řešení je, že důvodem selhání vložení je nějaký druh chycitelné chyby SQL (jako je porušení klíče, chyba neshoda dat/typ převodu atd.). Struktura by vypadala takto:

BEGIN TRAN

BEGIN TRY
  INSERT INTO foo(col_a,col_b,col_c,recdate)
  SELECT col_a,col_b,col_c,recdate
  FROM bar
  WHERE recdate BETWEEN @startdate AND @enddate

  DELETE FROM bar
  WHERE recdate BETWEEN @startdate AND @enddate

  COMMIT TRAN
END TRY
BEGIN CATCH
  ROLLBACK TRAN
END CATCH

Způsob, jakým tato struktura funguje, dojde-li k chybě v INSERT nebo DELETE, celá akce bude vrácena zpět. To zaručuje, že celá akce musí být úspěšná, aby mohla být dokončena. Pokud jste cítili, že je to nutné, můžete jej kombinovat s THROW pro rok 2012 nebo RAISERROR v roce 2008 a předchozí přidat další logiku a vynutit vrácení zpět, pokud tato logika nebyla splněna.

Další možností je podívat se na SET XACT_ABORT ON , i když mám pocit, že syntaxe TRY/CATCH vám dává větší granularitu.

13
Mike Fal

Pokud vaše archivní tabulka ne .

  • Jsou na něm definovány spouštěče.
  • Zúčastněte se na obou stranách omezení ZAHRANIČNÍ KLÍČ.
  • Mít KONTROLNÍ omezení nebo povolená pravidla.

Dalo by se to také udělat v jednom statenentu.

DELETE FROM source_table
OUTPUT deleted.Foo,
       deleted.Bar,
       SYSUTCDATETIME()
INTO archive_table(Foo, Bar, archived)
WHERE  Foo = 1; 

To buď uspěje, nebo selže jako jednotka a také se vyhne možným závodním podmínkám s tím, že se řádky přidají mezi INSERT do archivu a DELETE (i když vaše klauze WHERE může dobře přesto je to velmi nepravděpodobné).

19
Martin Smith

Zkuste to:

INSERT dbo.newtable(
      name,
      department,
      Salary
) SELECT 
            name,
            FirstName,
            Lastname
      FROM    (
           DELETE dbo.oldtable
           OUTPUT
                   DELETED.name,
                   DELETED.department,
                   DELETED.Salary
           WHERE ID  IN ( 1001, 1003, 1005 )
      ) AS RowsToMove;

SELECT * FROM dbo.newtable;
SELECT * FROM dbo.oldtable;
1
Nadeem

Způsob, jakým jsem přemýšlel o provádění archivace (což určitě také není dokonalé), je přidat do nové archivní tabulky bitový sloupec jako „Archivováno“, který by měl po úspěšném přenosu záznamu hodnotu 1. Jakmile přenesete všechny záznamy, můžete provést operaci smazání a zároveň hledat tuto hodnotu pole „Archivováno“ 1, tj. True z archivované tabulky.

A souhlasím s Mikem ohledně používání Try/Catch.

1
avakharia