2009-10-22 7 views
8

J'essaie d'archiver les enregistrements d'une table dans une base de données à une table identique dans une base de données d'archives. Je dois être en mesure de faire une insertion pour tous les enregistrements avec une date supérieure à trois ans, puis supprimer ces lignes. Cependant, cette table contient des millions d'enregistrements qui sont en direct, donc je veux exécuter ceci dans une boucle d'environ 100 à 1000 morceaux à la fois. Jusqu'à présent, ma procédure stockée fait l'ensemble de l'instruction insert, puis une instruction delete (dans une transaction) avec essentiellement la même clause WHERE que l'instruction insert. Ma boucle WHILE recherche la date la plus ancienne dans le tableau pour déterminer quand la boucle est terminée. Une partie de cela semble assez inefficace. Est-ce que je peux faire une insertion et une suppression sur le morceau d'enregistrements sans avoir à les rechercher deux fois dans la même exécution de boucle? Existe-t-il une meilleure façon de déterminer quand l'instruction WHILE est terminée? Exécution de MS SQL Server 2000.Script SQL Archive

Ceci est ma procédure actuelle (ISAdminDB est la principale DB, IsArchive est l'archive DB):

WHILE ((SELECT MIN([MyTable].[DateTime]) FROM [ISAdminDB].[dbo].[MyTable]) < DATEADD(d, -(3 * 365), GetDate())) 
BEGIN 

INSERT INTO [ISArchive].[dbo].[MyTable] 
(<Fields>) 
SELECT TOP 1000 (<Fields>) 
FROM [ISAdminDB].[dbo].[MyTable] 
WHERE 
    [MyTable].[DateTime] < DATEADD(d, -(3 * 365), GetDate()) 
AND UniqueID in (SELECT TOP 1000 UniqueID FROM [ISAdminDB].[dbo].[MyTable] ORDER BY [MyTable].[DateTime] ASC) 

BEGIN TRAN 
DELETE FROM [ISAdminDB].[dbo].[MyTable] 
WHERE [MyTable].[DateTime] < DATEADD(d, -(3 * 365), GetDate()) 
AND (UniqueID in (SELECT TOP 1000 UniqueID FROM [ISAdminDB].[dbo].[MyTable] ORDER BY [MyTable].[DateTime] ASC)) 
COMMIT 

END 
+0

qui SGBDR? SQL Server, MySQL, autre chose? – MartW

+0

Excuses, MS SQL Server 2000. – Kevin

+0

Je devine SQL Server – MartW

Répondre

6

Tout d'abord, vous supprimez des enregistrements avant une date précise, 3 il y a des années. Peu importe l'ordre dans lequel ils ont été supprimés, il vous suffit de les supprimer jusqu'à ce qu'il n'en reste plus. Vous pouvez également accélérer les choses en utilisant une table temporaire pour stocker les ID, et en stockant la date de coupure dans une variable et en y faisant référence à plusieurs reprises.

Nous avons donc maintenant:

DECLARE @NextIDs TABLE(UniqueID int primary key) 
DECLARE @ThreeYearsAgo datetime 
SELECT @ThreeYearsAgo = DATEADD(d, -(3 * 365), GetDate()) 

WHILE EXISTS(SELECT 1 FROM [ISAdminDB].[dbo].[MyTable] WHERE [MyTable].[DateTime] < @ThreeYearsAgo) 
BEGIN 
    BEGIN TRAN 

    INSERT INTO @NextIDs(UniqueID) 
     SELECT TOP 1000 UniqueID FROM [ISAdminDB].[dbo].[MyTable] WHERE [MyTable].[DateTime] < @ThreeYearsAgo 

    INSERT INTO [ISArchive].[dbo].[MyTable] (<Fields>) 
     SELECT (<Fields>) 
     FROM [ISAdminDB].[dbo].[MyTable] AS a 
     INNER JOIN @NextIDs AS b ON a.UniqueID = b.UniqueID 

    DELETE [ISAdminDB].[dbo].[MyTable] 
    FROM [ISAdminDB].[dbo].[MyTable] 
    INNER JOIN @NextIDs AS b ON a.UniqueID = b.UniqueID 

    DELETE FROM @NextIDs 

    COMMIT TRAN 
END 
+0

Merci! J'apprécie votre contribution. Ça semble fonctionner. – Kevin

Questions connexes