-2

私たちのアプリケーションは、データを一定期間保持するため、データを削除しません。代わりに、データベースのほとんどのテーブルに「削除済み」(ビット) の列があり、削除時に 1 をマークします。それ以外の場合、デフォルトは 0 です。

データベース内のすべてのテーブルを反復処理し、「deleted」という名前の列が存在するかどうかを確認するストアド プロシージャを作成したいと考えています。存在する場合は、LastUpdatedUtc 列 (datetime2) に対してチェックを実行し、日付が過ぎているかどうかを確認します。生後 6 か月で削除済み = 1 の場合、行を削除します。

このアプリケーションは継続的に開発されているため、テーブルを追加することができます。そのため、テーブルごとに行を追加し、新しいテーブルが追加されるたびに忘れずにテーブルを追加するのではなく、テーブルを反復処理するスクリプトを作成したいと考えています。

これに対する SQL Server 2008 R2 ストアド プロシージャのヘルプは非常に役立ちます。

ありがとうございました。

EDIT(Omaerに感謝)これが私がこれまでに思いついたものです。良い方法を知っている人は教えてください。

IF OBJECT_ID('tempdb..#tmpTables') IS NOT NULL DROP TABLE #tmpTables
GO

CREATE TABLE #tmpTables
(
ID INT,
TableName NVARCHAR(100) NOT NULL
)
GO

SET NOCOUNT ON
GO

INSERT #tmpTables
SELECT [object_id], [name] FROM sys.all_objects WHERE type_desc = 'USER_TABLE' ORDER BY [name]

DECLARE @TN NVARCHAR(100)
DECLARE @SQL NVARCHAR(max)
DECLARE @PurgeDate VARCHAR(50)

SET @PurgeDate = DATEADD(MONTH, -6, GETUTCDATE())

WHILE (SELECT COUNT(*) FROM #tmpTables) > 0
BEGIN
    SELECT TOP 1 @TN = TableName FROM #tmpTables
    IF EXISTS(SELECT * FROM sys.columns WHERE name = 'deleted' AND OBJECT_ID = OBJECT_ID(@TN)) 
    BEGIN
        IF EXISTS(SELECT * FROM sys.columns WHERE name = 'LastUpdatedUtc' AND OBJECT_ID = OBJECT_ID(@TN))  
        BEGIN
            SET @SQL = 'SELECT Count(*) As Counter FROM ' + @TN + ' WHERE [deleted] = 1 AND [LastUpdatedUtc] < ''' + @PurgeDate + '''' -- this will be the delete line when the code is final, just outputting results for now
            EXEC(@SQL)
        END      
     END
    DELETE #tmpTables WHERE TableName=@TN
END

DROP TABLE #tmpTables
4

2 に答える 2

1

これは私の最初の試みであり、テストされていないため、いくつかのタイプミス/構文エラーがある可能性がありますが、これで始めることができます:

    declare @date6MonthsBack varchar(50)
    select @date6MonthsBack = dateadd(month, -6, getdate());

    declare c cursor for
        select 'delete from ' + quotename(name) + ' where [deleted] = 1 and [LastUpdatedUtc] <= ''' + @date6MonthsBack + '''' from sys.tables
        where object_id in (select object_id from sys.columns where name = 'deleted')
        and object_id in (select object_id from sys.columns where name = 'LastUpdatedUtc')

    declare @sql varchar(max)
    open c; fetch next from c into @sql
    while (@@fetch_status = 0) begin
        print(@sql)
        --exec(@sql) --uncomment this line to do the actual deleting once you have verified the commands.
    fetch next from c into @sql; end
    close c; deallocate c
于 2013-06-03T20:29:21.967 に答える
0

sp_MSforeactableループやカーソルの代わりに、文書化されていない手順を使用できます。以下のコードのようなもの。コードを実行し、で実行されるプロシージャを作成しましたsp_MSforeachtable。欠点は、手順が文書化されておらず、次の SQL Server リリースでサポートされない可能性があることです。

IF OBJECT_ID('dbo.usp_cleanup') IS NULL
    EXEC ('CREATE PROCEDURE dbo.usp_cleanup AS SELECT 1')
GO

ALTER PROCEDURE dbo.usp_cleanup
    @sTblName VARCHAR(200)
AS
BEGIN
    -- your variables
    DECLARE @PurgeDate  VARCHAR(50)
    DECLARE @SQL        VARCHAR(MAX)

    SET @PurgeDate      = DATEADD(MONTH, -6, GETUTCDATE())

    -- we can check columns existence in one condition
    IF
        EXISTS(SELECT * FROM sys.columns WHERE name = 'deleted' AND OBJECT_ID = OBJECT_ID(@sTblName)) 
        AND EXISTS(SELECT * FROM sys.columns WHERE name = 'LastUpdatedUtc' AND OBJECT_ID = OBJECT_ID(@sTblName))
        BEGIN
            SET @SQL = 'SQL CODE GOES HERE' -- this will be the delete line when the code is final, just outputting results for now
            PRINT @SQL
            --EXEC(@SQL)                    -- uncomment for execution
        END
    ELSE
    -- for debugging
        BEGIN
            PRINT @sTblName + ' has no [delete] and [LastUpdatedUtc] columns'
        END
END


EXEC sp_MSforeachtable 'exec usp_cleanup ''?'''
GO
于 2013-06-04T09:02:44.183 に答える