【问题标题】:Create "loop" to drop tables with specific names/criteria创建“循环”以删除具有特定名称/条件的表
【发布时间】:2021-11-26 21:48:27
【问题描述】:

目前,我正在尝试从我的数据库中删除多个表。但只有那些名称以特定字符串开头或表名称完全符合我的通配符/下划线标准的那些。

在 Oracle 中,我使用了类似的东西,我正在 SQL Server Management Studio 中寻找与之等效的东西:

begin
  for i in (select TABLE_NAME 
              from  USER_TABLES 
              where TABLE_NAME = 'TABLE_____NAME'
             )
  loop
    execute immediate 'DROP TABLE '||i.TABLE_NAME||' CASCADE CONSTRAINTS PURGE';
  end loop;             
end;

当我开始使用 SQL Server 时,我开始意识到,SQL Server 不提供简单循环。

我设法创造了这样的东西:

SELECT 'IF OBJECT_ID(''' +TABLE_NAME + ''') IS NOT NULL BEGIN DROP TABLE [' + TABLE_NAME + '] END;' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE 'TABLE_____NAME'

...这至少给了我一个复制粘贴的列表。我认为上面的解决方案在检查对象 ID 方面是一种过度杀伤,但它工作正常。我不确定是否需要检查 Object id。

最后,我正在寻找一个更简单的解决方案,主要是针对我在 Oracle 中使用的类似循环的解决方案。我永远不知道它会有多少张桌子,所以计数器解决方案(我在研究期间经常发现)不是一种选择(至少据我所知)。

有什么想法吗?提前谢谢你。

有谁知道如何在 SQL Server 中实现 Oracle 循环工作

【问题讨论】:

  • WHILE 看起来很简单?
  • 一个游标也可以用来做这个,不是那么简单,但它会工作

标签: sql sql-server tsql


【解决方案1】:

删除表大概是一次性的过程,并且是您真正想要确定的事情。

我通常只是动态生成drop 语句的列表,然后您可以将其直接粘贴到 Management Studio 查询窗口中以直观地确认它们是正确的,然后您就可以执行脚本了。

select Concat_Ws(' ','drop table', QuoteName(name), ';')
from sys.tables
where name like 'TABLE_____NAME' 

【讨论】:

  • 嘿,谢谢。这个想法是在没有预先检查的情况下进行。但是之后启动所有这些命令会很好。
  • @lilaaffe 以我的经验,自动删除对象是意外发生的一个滴答作响的时钟,但是您可以简单地将上述内容分配给一个字符串并 exec 它。
【解决方案2】:

我会使用“while”来遍历准备好的脚本表中标识列提取的脚本文本。

Declare @RowNumber As Int = 1
Declare @Cnt As Int
Declare @schema_name sysname = '<your schema>'
Declare @QueryText nVarChar(max)

Create Table #Script (ID Int Identity(1,1), QueryText nVarChar(max))

Insert Into #Script (QueryText)
Select Concat(N'IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N''',
                          Quotename(@schema_name), N'.',Quotename([name]),N''') AND type in (N''U'')) DROP TABLE ',
                          Quotename(@schema_name), N'.',Quotename([name]))
From sys.tables 
Where [name] Like 'TABLE_____NAME'

Select @Cnt = Count(*) From #Script

While (@RowNumber<=@Cnt)
    Begin
        Select @QueryText = QueryText From #Script Where ID=@RowNumber

        Exec sp_executesql @QueryText

        RAISERROR ('%s', 0, 1, @QueryText) WITH NOWAIT

        Select @RowNumber=@RowNumber+1
    End

或者您可以使用 string_agg 获取脚本来删除所有表并一次性运行它而不使用循环。

Declare @QueryText nVarChar(max)
Declare @max nVarChar(max) = ''
Declare @schema_name sysname = '<your schema>'

Select @QueryText=String_Agg(Concat(@max, N'IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N''',
                                           Quotename(@schema_name), N'.',Quotename([name]),N''') AND type in (N''U'')) DROP TABLE ',
                                           Quotename(@schema_name), N'.',Quotename([name])), ' ')
From sys.tables 
Where [name] Like 'TABLE_____NAME'

Execute sp_executesql @QueryText

【讨论】:

  • 嘿,感谢您的回答 :) 不知何故,工作室告诉我它已成功完成,但我的表仍然存在。下划线'_'用作通配符,它​​仍然这样工作吗?你的秒,更短的方法看起来还是不错的:)
  • 嘿,不客气。如果下划线表示任何单个字符,那么您需要“Like”运算符。我使用 Like 更改了解决方案。在任何情况下,强烈建议在通过 sp_executesql 执行 @QueryText 变量之前检查它的内容。
  • 您还应该指定表架构的实际名称,而不是
  • 谢谢,这就是原因,愚蠢的我自己都没见过 :) 你更短的解决方案效果很好,它可以工作:) 谢谢
  • 不客气。我很高兴能提供帮助。
猜你喜欢
  • 2020-06-10
  • 1970-01-01
  • 2012-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多