运行DELETE语句存储在表中的某些表名

时间:2013-05-02 17:21:36

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

我有一个表存储某些表的名称 - tableNames 。我想在其中一些表上运行DELETE语句(删除它们所代表的表中的所有行,而不是从 tableNames 中删除它们)。我以为我可以做到

DELETE FROM (SELECT tableName FROM tablesNames WHERE ...) AS deleteTables

但是我一直收到错误的语法错误。我还想过迭代WHILE循环中的表并使用变量存储,但我希望有更简单的方法。具体来说,这适用于Microsoft SQL

6 个答案:

答案 0 :(得分:5)

你不能那样做,因为内部SELECT只是你要删除的另一个集合。

基本上你要创建一个表名表并告诉DB删除它。如果没有动态sql和EXEC

,即使迭代它们也行不通

您是否需要自动执行此过程?

我过去所做的就是这样的事情

SELECT
    'DELETE ' + tableName
FROM
    tablenames
WHERE
   [conditions]

您的输出将如下所示:

DELETE myTableName1
DELETE myTableName2
DELETE myTableName3

然后只需将此查询的结果复制出窗口并运行它们。

如果您需要在SQL中自动执行此操作,您可以连接结果中的所有输出字符串,并将它们作为参数发送到EXEC调用。

答案 1 :(得分:3)

在这方面,您可以将SQL视为一种编译语言,如C / C ++。 SQL语句由“编译器”评估,并完成某些检查。其中一项检查是针对查询中直接引用的表和列的存在(和权限)。在构建查询时,代码中存在精确的表名必须,以便编译器可以对其进行验证。

好消息是SQL也是一种动态语言。这意味着您可以编写一个过程来将查询构建为字符串,并告诉数据库使用EXEC命令执行该字符串。此时,所有相同的“编译器”规则都适用,但由于您能够将表名直接插入到SQL字符串中,因此查询将通过。

问题在于这也具有安全隐患。最好还是针对像information_schema.Tables这样的资源检查你的表,以避免潜在的注入攻击。不幸的是,如果您要删除整个表格,您的整个模型可能已经被怀疑,这样您就无法保证某人不会注入您真正想要保留的表格名称。但是根据这些人口的填充方式,你也可能没问题。

答案 2 :(得分:2)

尝试使用cursor:

DECLARE @tableName varchar(255)

DECLARE cur cursor for select tableName from tableNames where (...)

OPEN CUR
FETCH NEXT FROM cur into @tableName

WHILE @@FETCH_STATUS = 0
BEGIN
exec('DELETE ' + @tableName)
FETCH NEXT FROM cur into @tableName 
END

CLOSE cur
DEALLOCATE cur

答案 3 :(得分:1)

假设不存在潜在的约束错误,一个有趣的可能性是未记录的过程sp_MSforeachtable,它允许您对查询返回名称的所有表应用给定的操作:

EXEC sp_MSforeachtable @command1 = 'delete from ?'
, @whereand = 'and o.name IN (SELECT tableName FROM tablesNames WHERE ...)'

另外http://weblogs.asp.net/nunogomes/archive/2008/08/19/sql-server-undocumented-stored-procedure-sp-msforeachtable.aspx以获得更多阅读。

答案 4 :(得分:0)

delete语句一次只能使用一个表名。

完整语法为documented here,但它是TL; DR ...简而言之,您必须使用循环。

答案 5 :(得分:0)

我正在使用与@Pavel类似的游标以及我的索引列表以重新组织它们。像这样的操作是游标的极少原因之一。