在 SQL Server 中通过游标(获取表名)删除所有表



我有一个带有stg_table列的元数据表。这是架构中STAGE数据库表的名称dbo。如果列为"选择"insert_type则我想删除表。

元数据示例:https://i.stack.imgur.com/ZBQJp.jpg

和我的光标代码:

declare kursor cursor for 
select * 
from METADATA.dbo.META_SOURCESTAGE;
declare @insert_type varchar(15), 
@stg_table varchar(30), 
@src varchar(80), 
@SQL varchar(254);
open kursor
fetch next from kursor into @insert_type, @stg_table, @src;
while @@FETCH_STATUS = 0
begin
if @insert_type = 'select'
begin
select @SQL = 'IF OBJECT_ID('+@stg_table+') IS NOT NULL DROP TABLE '+@stg_table
exec(@SQL)
fetch next from kursor into @insert_type, @stg_table, @src;
end
if @insert_type = 'bulk'
execute ('truncate table ' + @stg_table);
print @stg_table;
fetch next from kursor into @insert_type, @stg_table, @src;
end
close kursor;
deallocate kursor;

我想通过在元数据表创建的光标从 STAGE.dbo.* 中删除所有现有表。

我收到一个错误:

Msg 4104,级别 16,状态 1,第 2 行 无法
绑定多部分标识符"STAGE.dbo.STG_KLIENT"。 STAGE.dbo.STG_MELDUNEK

Msg 4104,级别 16,状态 1,第 2 行 无法
绑定多部分标识符"STAGE.dbo.STG_MIEJSCOWOSC"。
STAGE.dbo.STG_PRACOWNIK

@EDIT 更改了代码 - 添加了开始/结束,但仍然收到相同的错误。

它抱怨无法绑定OBJECT_ID调用,您的代码会导致如下结果:

IF OBJECT_ID(STAGE.dbo.STG_KLIENT) IS NOT NULL DROP TABLE STAGE.dbo.STG_KLIENT

DROP TABLE部分很好,但是您需要在调用OBJECT_ID时引用表名,因为它需要(N)VARCHAR输入,因此请使用:

select @sql = 'IF OBJECT_ID('''+@stg_table+''') IS NOT NULL DROP TABLE '+@stg_table
--                           ^^            ^^

此外,您的代码到处都是。它将跳过一些表,因为您正在做的是:

  1. 从光标中获取(第一个结果,让我们假设选择类型)
  2. 检查@insert_type是否="选择",为真,让我们输入块
    • 删除表(如果存在)
    • 从游标中获取(第二个结果,让我们再次假设选择类型
    • 如果阻止,则离开
  3. 检查@insert_type是否="插入",假,不要截断
  4. 打印表名
  5. 从光标获取下一个 ->第三个结果,你只是对第二个结果做了什么,你应该把它放下。

这是一个略微改进的版本:

while @@FETCH_STATUS = 0
begin
if @insert_type = 'select'
begin
select @sql = 'IF OBJECT_ID('''+@stg_table+''') IS NOT NULL DROP TABLE '+@stg_table
end
else if @insert_type = 'insert'
begin
select @sql = 'TRUNCATE TABLE ' + @stg_table
end
print @sql -- "debugging"
-- only do those once if you can, so you don't get lost in how the code branches
exec sp_executesql @sql
fetch next from kursor into @insert_type, @stg_table, @src;
end

此外,您实际上并不需要光标。您可以生成一个大查询并执行一次。

DECLARE @sql NVARCHAR(MAX) = ''
SELECT @sql += CONCAT(CASE
WHEN meta.insert_table = 'select'
AND OBJECT_ID(meta.stg_table) IS NOT NULL
THEN CONCAT('DROP TABLE ', meta.stg_table)
WHEN meta.insert_table = 'insert'
THEN CONCAT('TRUNCATE TABLE', meta.stg_table)
END,
';', CHAR(13), CHAR(10)) -- add newline for easier reading
FROM METADATA.dbo.META_SOURCESTAGE meta
PRINT @sql
EXEC sp_executesql @sql

这应该有效,虽然我还没有测试过它,但我希望你明白这个想法。

最新更新