循环通过不同日期的不同表

时间:2014-07-25 08:07:17

标签: sql sql-server sql-server-2008-r2

我们有一个遗留应用程序,它使用以下命名约定创建了多个表:table_20140618,table_20140623等,其中日期是程序运行的时间。我现在正在尝试清理数据库,并删除其中的一些表。

在每个表中有两个字段:DateStarted和DateFinished。我想选择表(然后删除它们),其中DateStarted有值,而DateFinished是非null。

目前我正在使用以下查询来选择以'table_'开头的所有表 如:

Select (TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_TYPE = 'BASE TABLE' 
AND TABLE_NAME LIKE 'table_%';

我不确定如何通过在他们的字段中搜索来将所有表格放在一起。我可以通过代码完成它,但这应该意味着数据库上有多次点击。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

在我上面的第一条评论之后做了这个,但你应该能够改变代码以适合你的规格。基本上,这将使用动态SQL根据您的过滤器和条件生成命令。因此,您可以在 SELECT @SQL = ... 部分中使用您想要的任何条件来检查日期,然后在满足条件时添加表名。

该脚本返回一个包含表名和drop命令的列表,因此您可以在执行此操作之前检查自己正在执行的操作。但是从那里你可以复制drop命令列表并在需要时执行它。

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

CREATE TABLE #TABLES (ROWNMBER INT IDENTITY(1,1), TABLENAME VARCHAR(256) COLLATE DATABASE_DEFAULT)

/*
-- Old code to fetch ALL tables with specified name
INSERT INTO #TABLES
SELECT name
FROM sys.tables 
WHERE name LIKE 'table[_]%'
*/

-- Updated code to fetch only those tables which contain the DateStarted and DateFinished columns
INSERT INTO #TABLES
SELECT TAB.name
FROM sys.tables TAB
LEFT JOIN sys.columns C1 on C1.object_id = TAB.object_id
    AND C1.name = 'DateStarted'
LEFT JOIN sys.columns C2 on C2.object_id = TAB.object_id
    AND C2.name = 'DateFinished'
WHERE TAB.name LIKE 'table[_]%'
AND C1.name IS NOT NULL AND C2.name IS NOT NULL

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

CREATE TABLE #DROPPABLE_TABLES (TABLENAME VARCHAR(256) COLLATE DATABASE_DEFAULT)

DECLARE @ROW_NOW INT, @ROW_MAX INT, @SQL VARCHAR(MAX), @TABLENAME VARCHAR(256)
SELECT @ROW_NOW = MIN(ROWNMBER), @ROW_MAX = MAX(ROWNMBER) FROM #TABLES

WHILE @ROW_NOW <= @ROW_MAX
BEGIN
    SELECT @TABLENAME = TABLENAME FROM #TABLES WHERE ROWNMBER = @ROW_NOW

    SELECT @SQL = 
'IF (SELECT COUNT(*) FROM '+@TABLENAME+' WHERE DateStarted IS NOT NULL) > 0 
    AND (SELECT COUNT(*) FROM '+@TABLENAME+' WHERE DateFinished IS NOT NULL) > 0
SELECT '''+@TABLENAME+''''

    INSERT INTO #DROPPABLE_TABLES   
    EXEC(@SQL)

    SET @ROW_NOW = @ROW_NOW+1
END

SELECT *, 'DROP TABLE '+TABLENAME DROPCOMMAND FROM #DROPPABLE_TABLES

修改 根据你的评论,似乎并非所有这些表都有这些列。您可以使用以下脚本来标识所述表以及缺少哪个列,以便您可以进一步检查它们。您可以使用相同的想法来过滤第一个查询的结果,只计算具有这些列的表。

SELECT TAB.name TABLENAME
    , CASE WHEN C1.name IS NULL THEN 'Missing' ELSE '' END DateStarted_COL
    , CASE WHEN C2.name IS NULL THEN 'Missing' ELSE '' END DateFinished_COL
FROM sys.tables TAB
LEFT JOIN sys.columns C1 on C1.object_id = TAB.object_id
    AND C1.name = 'DateStarted'
LEFT JOIN sys.columns C2 on C2.object_id = TAB.object_id
    AND C2.name = 'DateFinished'
WHERE TAB.name LIKE 'table[_]%'
AND (C1.name IS NULL 
    OR C2.name IS NULL)