【发布时间】:2015-11-19 12:33:12
【问题描述】:
我支持第三方软件包的 SQL 数据库。他们有很多他们所谓的“影子表”,实际上只是审计表。这一切都很好,但是他们的系统没有清理这些表,所以这取决于我。他们还会在每次升级时添加新的“影子表”,恕不另行通知。我们清除表的旧方法是使用一长串 DELETE FROM 语句,但这个列表变得非常长且难以维护。
为了尝试使清除过程更易于维护并自动捕获新的“影子表”,我编写了以下存储过程。存储过程有效,但我更愿意找出一种不使用游标和动态查询的方法,因为这将每天在许多不同的表上运行。有没有不使用游标和动态查询的替代方法?
DECLARE @workingTable varchar(128);
DECLARE @sqlText varchar(250);
DECLARE @CheckDate DATETIME = DATEADD(yy, -2, GETDATE());
DECLARE curKey SCROLL CURSOR FOR
SELECT name AS TableName
FROM dataTEST.sys.tables
WHERE (name like '%[_]h' OR name like '%[_]dh')
ORDER BY name
OPEN curKey
WHILE @@fetch_status = 0
BEGIN
FETCH NEXT FROM curKey INTO @workingTable
SET @sqlText = 'DELETE FROM DataTEST.dbo.' + @workingTable + ' WHERE LAST_MOD < ''' + CONVERT(CHAR(10), @CheckDate, 101) + ''';'
--PRINT @sqlText
EXEC (@sqlText)
END
CLOSE curKey
DEALLOCATE curKey
【问题讨论】:
-
我认为在调用
fetch之前不会设置@@fetch_status,从而导致while条件在第一次传递时不成立。这是您程序的准确副本吗? -
@ShannonSeverance 我已经删除了许多游标,但这是我写过的第一个游标,所以我不声称自己是专家,但这确实像写的那样工作。有一个奇怪的行为,它不能运行两次;第二次它什么也不做。为了解决这个问题,我必须关闭文件并重新打开它是 SSMS,但这超出了我的问题范围。
-
我问是因为它不适合我。错误行为与我预期的不同。它第二次不起作用,因为
@@fetch_status仍然是该连接上最后一次提取的-1。那是完成先前运行的获取。请参阅msdn.microsoft.com/en-us/library/ms187308.aspx。为避免重复提取,我通常会使用declare ... open ... while (1=1) begin fetch ... if @@fetch_status<> 0 break /* else */ <do work> end close .... deallocate ... -
@ShannonSeverance 谢谢,我希望我在调试这个东西的时候就知道了。我不得不关闭并打开 .sql 文件十几次或更多次。我添加了您建议的更改。原始代码仍然为我运行(一次),没有任何问题。如果有什么不同,我会使用 2012 年。
标签: sql sql-server tsql dynamic-sql