小编典典

对没有动态SQL的多个表运行相同的查询

sql

我支持第三方软件包的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

阅读 177

收藏
2021-03-23

共1个答案

小编典典

无论如何,当您提前不知道表名时,无论如何我都不知道要摆脱动态SQL。SQL
Server具有一项功能,您可以在select语句中对返回的每一行进行一次变量分配。这可用于消除游标并将带有所有delete语句的一个字符串传递给SQL
Server以执行

DECLARE @sqlText nvarchar(MAX) = ''; -- initialize because NULL + 'x' is NULL
DECLARE @CheckDate DATETIME = DATEADD(YEAR, -2, GETDATE());

SELECT @sqlText = @SqlText + 'DELETE FROM dataTEST.dbo.' + QUOTENAME(name) 
    + ' WHERE LAST_MOD < @CheckDate ; '
FROM dataTEST.sys.tables
WHERE (name like '%[_]h' OR name like '%[_]dh')
ORDER BY name

IF @@ROWCOUNT > 0 
    EXEC sp_executesql @sqlText
        , N'@CheckDate DATETIME'
        , @CheckDate
2021-03-23