sql - 在没有动态 SQL 的情况下对多个表运行相同的查询

标签 sql sql-server tsql dynamic-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

最佳答案

当您提前不知道表名时,我不知道如何摆脱动态 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 

关于sql - 在没有动态 SQL 的情况下对多个表运行相同的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32210193/

相关文章:

具有空主体的 SQL Server 存储过程

sql - 在tsql中使用 bool 代数来避免CASE语句或处理复杂的WHERE条件

mysql - 无法创建 MySQL View

sql - mssql按小时计算总数

javascript - 使用c#将用户数据设置为HTML标签

sql-server - 自动将 GRANT EXECUTE 添加到 MSSQL Management Studio 中的 Drop&Create 脚本

sql - 我可以使用什么 GUID 作为占位符

sql - 如何控制 SQL Server 中新标识列的分配顺序?

mysql - 错误 #1064 - 您的 SQL 语法有错误;检查与您的 MariaDB 服务器版本相对应的手册以获取正确的语法

mysql - 基于在数据库中搜索整数或长字符串(唯一)的性能?