如何在一个查询中删除具有公共前缀的多个表?


17

我正在使用Microsoft SQL Server 2008.我的问题是:如何在一个查询中删除多个具有公共前缀的表?

该表名称类似:

LG_001_01_STLINE, 
LG_001_02_STFICHE

Answers:


32

您可以使用目录视图构建字符串,例如:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += '
DROP TABLE ' 
    + QUOTENAME(s.name)
    + '.' + QUOTENAME(t.name) + ';'
    FROM sys.tables AS t
    INNER JOIN sys.schemas AS s
    ON t.[schema_id] = s.[schema_id] 
    WHERE t.name LIKE 'LG_001%';

PRINT @sql;
-- EXEC sp_executesql @sql;

当然存在潜在的陷阱,例如,如果这些表具有外键关系,则需要先删除它们,或者安排输出以特定顺序删除表。

要仅获取表列表,请使用:

SELECT s.name, t.name 
  FROM sys.tables AS t 
  INNER JOIN sys.schemas AS s 
  ON t.[schema_id] = s.[schema_id] 
  WHERE t.name LIKE 'LG_001%';

非常感谢您记住“安排输出以一定顺序删除表”!
sdlins

4

我运行此查询,然后将结果粘贴回查询窗口以删除所有表:

SELECT 'DROP TABLE ' + NAME from sys.tables
ORDER BY NAME

如果要删除所有表,但保留名称以A,B,C或D开头的表:

SELECT 'DROP TABLE ' + NAME from sys.tables
WHERE NAME NOT LIKE '[ABCD]%'
GROUP BY NAME

-1

这使您可以删除更多的表。

declare 
@cursor as cursor, 
@FTABLE as varchar(500) 
set @cursor = CURSOR FOR 
select 'drop table ' + NAME + ';' 
from sys.tables 
where not SUBSTRING(NAME,10,3) in 
( 
'310', 
'311', 
'312', 
'313', 
'314', 
'320', 
'321', 
'322' 
) 
open @cursor 
fetch next from @cursor into @FTABLE 
while (@@FETCH_STATUS =0) 
begin 
        exec(@FTABLE) 
        print @FTABLE 
fetch next from @cursor into @FTABLE 
end 
close @cursor 
deallocate @cursor 

2
大于什么?您是否可以修改SQL,以便它查找具有公共前缀的表,例如OP要求的?
dezso 2012年

-1

我喜欢我写的这篇文章:

  DECLARE @chv_LG001_TableName nvarchar (100)
  DECLARE @chv_DROP_LG001_Tables nvarchar(100)
  DECLARE @chv_LG001_Table_Count int

  SET @chv_LG001_Table_Count = (SELECT count(OBJECT_NAME(id))
        FROM SYSINDEXES
        WHERE OBJECTPROPERTY(id,'isUserTable')=1 AND indid < 2
            and OBJECT_NAME(id) like 'LG_001%')

 IF @chv_LG001_Table_Count > 0
    BEGIN

    DECLARE  Drop_LG001_Tables_Cursor CURSOR FOR
      -- This query will give you the table list you are wanting
        SELECT OBJECT_NAME(id)
        FROM SYSINDEXES
        WHERE OBJECTPROPERTY(id,'isUserTable')=1 AND indid < 2
            and OBJECT_NAME(id) like 'LG_001%'

    OPEN Drop_LG001_Tables_Cursor
    FETCH NEXT FROM Drop_LG001_Tables_Cursor INTO @chv_LG001_TableName 
    WHILE @@FETCH_STATUS = 0 

    BEGIN           

    SET @chv_DROP_LG001_Tables = 'DROP TABLE ' + '[' + @chv_LG001_TableName + ']'

    --Print @chv_DROP_LG001_Tables 
-- Uncomment the next line when you are ready because it WILL clear out these tables. 
    --EXEC sp_executesql @chv_DROP_LG001_Tables

    FETCH NEXT FROM Drop_LG001_Tables_Cursor
    INTO @chv_LG001_TableName

    END

    CLOSE Drop_LG001_Tables_Cursor
    DEALLOCATE Drop_LG001_Tables_Cursor

END

2
这里有很多问题。(1)光标脚手架是复杂且不必要的。(2)在使用流水线游标时,至少应使用STATIC和/或LOCAL FAST_FORWARD](sqlperformance.com/2012/09/t-sql-queries/cursor-options)。(3)您不应使用已弃用的向后兼容视图sysindexes。(4)您的脚本假定所有表都在dbo架构中(或更糟糕的是,执行用户的默认架构,甚至可能不是dbo)。
亚伦·伯特兰

-2

可以使用execute以下方法完成此操作:

declare @sql1 nvarchar(max) 
SELECT @sql1 =
 STUFF(
  (
    select ' drop table dbo.[' + name + ']'

FROM         sys.sysobjects AS sobjects
WHERE     (xtype = 'U') AND (name LIKE 'GROUP_BASE_NEW_WORK_%')
        for xml path('')
   ),
        1,1,'')

        execute sp_executesql @sql1

1
这本质上是对已接受答案的一种变体,但没有任何改进。区别仅在于您选择了以下假设:1)应该使用默认模式dbo,以及2)名称永远不能包含]-在OP的情况下,这两个都是正确的,但这仍然是一个好习惯提及这些假设的想法,因为随之而来的警告对于其他人可能并不完全清楚。但是,正如我一开始所说的那样,我对这个答案的主要问题是,它只是在不增加任何新价值的情况下重申了已经存在的建议。
Andriy M

-3
SELECT s.name, t.name 
  FROM sys.tables AS t 
  INNER JOIN sys.schemas AS s 
  ON t.[schema_id] = s.[schema_id] 
  WHERE t.name LIKE 'LG_001%';

运行以上查询并将结果保存到csv中。然后在记事本中打开该CSV。然后执行Ctrl + H,用DROP TABLE SCHEMA替换架构,这将为您提供所有放置查询,将该大sql复制并粘贴到sql工具中并执行

如果你的结果是

myschema.table1
myschema.table2

替换后,它看起来像这样

DROP TABLE MYSCHEMA.TABLE1
DROP TABLE MYSCHEMA.TABLE2

-1为什么要在Excel中复制/粘贴并生成放置命令?您可以使用PRINT语句轻松地做到这一点。与最高投票答案相比,您的答案如何?
Kin Shah 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.