-2

我们的应用程序不会删除数据,因为我们会保留一段时间,而是在数据库的大多数存储数据的表中都有一个“已删除”(位)列,删除时我们将其标记为 1,否则默认为 0。

我想创建一个存储过程来迭代数据库中的所有表,检查是否存在名为“deleted”的列,如果存在,我对 LastUpdatedUtc 列(datetime2)进行检查,如果日期结束6 个月大并删除 = 1 然后我们删除该行。

这个应用程序正在持续开发中,因此可以添加表,这就是为什么我想创建一个迭代表的脚本,而不是为每个表添加一行,并记住在添加新表时添加它们。

SQL Server 2008 R2 存储过程中对此的任何帮助都会有很大帮助。

谢谢你。

编辑(谢谢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 回答