在 IF 语句和 WHILE 循环中执行 sp_executesql
exec sp_executesql in an IF stament and WHILE loop
我的脚本有问题,它会搜索 table 名称中包含 'Dummy' 的所有 table。我有一个 SELECT 查询,结果将是要删除的 table。
SELECT Row_Number() Over (Order By name) As RowNum
, name
FROM sys.all_objects
WHERE type = 'U'
and name like '%Dummy%'
and schema_id = @schemaID
它返回:
RowNum name
1 Dummy
2 DummyJoinTbl1
3 DummyJoinTbl2
4 DummyJoinTbl3
但是当我执行下面的脚本时,
DECLARE
@schemaName nvarchar(100),
@schemaID int,
@tblName nvarchar(100) = '',
@cnt int = 1,
@rowNumber int = 1,
@SQL nvarchar(100)
SET @schemaName = (select SCHEMA_NAME()) -- this is dbo
SET @schemaID = (select SCHEMA_ID()) -- this is 1
BEGIN
WHILE (@cnt > 0)
BEGIN
SELECT @tblName = +name
FROM
(
SELECT Row_Number() Over (Order By name) As RowNum
, name
FROM sys.all_objects
WHERE type = 'U'
and name like '%Dummy%'
and schema_id = @schemaID
) ReferenceTable
WHERE RowNum = @rownumber
SET @cnt = @@ROWCOUNT
SET @rownumber = @rownumber + 1
IF (@cnt > 0)
BEGIN
PRINT 'DROP TABLE ' + @schemaName + '.' + @tblName + ' - RowCount:' + cast(@cnt as nvarchar(100))
set @SQL = 'DROP TABLE ' + @schemaName + '.' + @tblName
exec sp_executesql @SQL
END
END
PRINT 'DONE'
END
它返回的结果:
DROP TABLE dbo.Dummy - RowCount:1
DROP TABLE dbo.DummyJoinTbl2 - RowCount:1
DONE
遗漏其他 table 的原因可能是什么?当我删除
set @SQL = 'DROP TABLE ' + @schemaName + '.' + @tblName
exec sp_executesql @SQL
它将打印所有 tables。
DROP TABLE dbo.Dummy - RowCount:1
DROP TABLE dbo.DummyJoinTbl1 - RowCount:1
DROP TABLE dbo.DummyJoinTbl2 - RowCount:1
DROP TABLE dbo.DummyJoinTbl3 - RowCount:1
DONE
请注意,给定的 table 都是空的。提前致谢。
这是使用游标的完美场所,如果这样做,您需要的代码会少很多。这是一个简化的示例,它假设您只想从单个数据库中删除表:
USE TempDB1;
CREATE TABLE test1 (i INT);
CREATE TABLE test2 (i INT);
CREATE TABLE test3 (i INT);
CREATE TABLE test4 (i INT);
DECLARE @tableName VARCHAR(200),
@sql NVARCHAR(MAX);
DECLARE c CURSOR FAST_FORWARD FOR
SELECT name
FROM sys.all_objects
WHERE type = 'U'
AND name LIKE '%test%'
AND schema_id = SCHEMA_ID();
OPEN c;
FETCH NEXT FROM c INTO @tableName;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql = 'DROP TABLE ' + @tableName;
PRINT @sql;
EXEC sp_executesql @sql;
FETCH NEXT FROM c INTO @tableName;
END;
CLOSE c;
DEALLOCATE c;
那是因为删除第一个 table 后 select 语句的结果变为下一个:
1 DummyJoinTbl1
2 DummyJoinTbl2
3 DummyJoinTbl3
是DummyJoinTbl1跳过的原因,因为@rownumber = 2。接下来循环@rownumber = 3,超过了记录数。
不要使用 WHERE RowNum = @rownumber
使用 SELECT TOP(1) @tblName = +name 没有嵌套 select 和 ROW_NUMBER()
在 WHILE 语句中使用 1 select 而不是 selecting N 次
也更好
我的脚本有问题,它会搜索 table 名称中包含 'Dummy' 的所有 table。我有一个 SELECT 查询,结果将是要删除的 table。
SELECT Row_Number() Over (Order By name) As RowNum
, name
FROM sys.all_objects
WHERE type = 'U'
and name like '%Dummy%'
and schema_id = @schemaID
它返回:
RowNum name
1 Dummy
2 DummyJoinTbl1
3 DummyJoinTbl2
4 DummyJoinTbl3
但是当我执行下面的脚本时,
DECLARE
@schemaName nvarchar(100),
@schemaID int,
@tblName nvarchar(100) = '',
@cnt int = 1,
@rowNumber int = 1,
@SQL nvarchar(100)
SET @schemaName = (select SCHEMA_NAME()) -- this is dbo
SET @schemaID = (select SCHEMA_ID()) -- this is 1
BEGIN
WHILE (@cnt > 0)
BEGIN
SELECT @tblName = +name
FROM
(
SELECT Row_Number() Over (Order By name) As RowNum
, name
FROM sys.all_objects
WHERE type = 'U'
and name like '%Dummy%'
and schema_id = @schemaID
) ReferenceTable
WHERE RowNum = @rownumber
SET @cnt = @@ROWCOUNT
SET @rownumber = @rownumber + 1
IF (@cnt > 0)
BEGIN
PRINT 'DROP TABLE ' + @schemaName + '.' + @tblName + ' - RowCount:' + cast(@cnt as nvarchar(100))
set @SQL = 'DROP TABLE ' + @schemaName + '.' + @tblName
exec sp_executesql @SQL
END
END
PRINT 'DONE'
END
它返回的结果:
DROP TABLE dbo.Dummy - RowCount:1
DROP TABLE dbo.DummyJoinTbl2 - RowCount:1
DONE
遗漏其他 table 的原因可能是什么?当我删除
set @SQL = 'DROP TABLE ' + @schemaName + '.' + @tblName
exec sp_executesql @SQL
它将打印所有 tables。
DROP TABLE dbo.Dummy - RowCount:1
DROP TABLE dbo.DummyJoinTbl1 - RowCount:1
DROP TABLE dbo.DummyJoinTbl2 - RowCount:1
DROP TABLE dbo.DummyJoinTbl3 - RowCount:1
DONE
请注意,给定的 table 都是空的。提前致谢。
这是使用游标的完美场所,如果这样做,您需要的代码会少很多。这是一个简化的示例,它假设您只想从单个数据库中删除表:
USE TempDB1;
CREATE TABLE test1 (i INT);
CREATE TABLE test2 (i INT);
CREATE TABLE test3 (i INT);
CREATE TABLE test4 (i INT);
DECLARE @tableName VARCHAR(200),
@sql NVARCHAR(MAX);
DECLARE c CURSOR FAST_FORWARD FOR
SELECT name
FROM sys.all_objects
WHERE type = 'U'
AND name LIKE '%test%'
AND schema_id = SCHEMA_ID();
OPEN c;
FETCH NEXT FROM c INTO @tableName;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql = 'DROP TABLE ' + @tableName;
PRINT @sql;
EXEC sp_executesql @sql;
FETCH NEXT FROM c INTO @tableName;
END;
CLOSE c;
DEALLOCATE c;
那是因为删除第一个 table 后 select 语句的结果变为下一个:
1 DummyJoinTbl1
2 DummyJoinTbl2
3 DummyJoinTbl3
是DummyJoinTbl1跳过的原因,因为@rownumber = 2。接下来循环@rownumber = 3,超过了记录数。 不要使用 WHERE RowNum = @rownumber
使用 SELECT TOP(1) @tblName = +name 没有嵌套 select 和 ROW_NUMBER()
在 WHILE 语句中使用 1 select 而不是 selecting N 次
也更好