【问题标题】:How to pick a table_name value from one table and delete records from the table_name table based on a condition?如何从一个表中选择一个 table_name 值并根据条件从 table_name 表中删除记录?
【发布时间】:2018-05-15 15:00:28
【问题描述】:

我们有一张桌子。让我们称之为Table_A。 Table_A 包含一堆 table_names 和与每个 table_name 关联的数值。参考下图

谁能帮我写一个查询: 从TABLE_A中一一选择table_names;转到该表,对照 Table_A 中的 NO_OF_DAYS 检查每条记录的 Date_inserted,如果该记录早于 Table_A 中的 NO_OF_DAYS,则从该特定表中删除该记录。

我猜我们必须为此查询创建动态值,但我很难。

所以,在上图中,查询应该:

  1. 从 Table_A 中选择第一个 table_name (T_Table1)
  2. 转到该表 (T_Table1)
  3. 根据条件检查 (T_Table1) 中每条记录的插入日期
  4. 如果条件(IF 记录在 NO_OF_DAYS 之前插入,在这种情况下为 90,则删除该记录;ELSE 移至下一个 记录)
  5. 转到 Table_A 中的下一个表 (T_Table2)
  6. 继续直到Table_A中的所有table_names都被执行完

【问题讨论】:

  • 是的,您是对的,您将需要使用动态 SQL。到目前为止,您尝试过什么?
  • 嗨 Larnu,我尝试使用以下查询 SET SQL = 'DELETE [' + dbo + '].[' + TABLE_NAME + '] where [Date_inserted ]

标签: sql sql-server dynamic parameter-passing


【解决方案1】:

您发布的尝试(在评论中)根本行不通。让我们先实际格式化一下,我们可以:

SET SQL = '
DELETE [' + dbo + '].[' + TABLE_NAME + '] 
where [Date_inserted ] < '
SET SQL = SQL + ' convert(varchar, DATEADD(day, ' + CONVERT(VARCHAR, NO_OF_DAYS) + ',' + '''' + CONVERT(VARCHAR, GETDATE(), 102) + '''' + '))'
PRINT SQL
EXEC (SQL) 

首先,我实际上不知道你在这里想要做什么。你有像[' + dbo + '] 这样的东西,这意味着你引用了dbo 列;当您使用SET 时,则不存在dbo 列。此外,变量在 SQL Server 中以 @ 为前缀;你没有。

无论如何,解决方案。有些人可能不喜欢这个,因为我使用的是CURSOR,而不是一次性完成所有操作。然而,我确实有我的理由。 CURSOR 实际上并不像许多人认为的那样是“坏”的东西;问题是人们经常错误地使用它们。例如,使用CURSOR 循环记录并创建层次结构是一个糟糕的主意;有更好的数据集方法。

那么,我的理由是什么?首先我可以参数化动态 SQL;这在CURSOR 之外会更难,因为我需要为每个DELETE 声明一个不同的参数。此外,对于CURSOR,如果DELETE 在一张桌子上失败,则不会在其他桌子上;一条长的动态 SQL 意味着如果其中一个事务失败,它们都将被回滚。此外,根据删除的大小,这可能是一个非常大的DELETE

但是,重要的是,您要了解我在这里所做的;如果你不这样做,这本身就是一个问题。如果您将来需要对其进行故障排除怎么办? SO 不是这样的支持网站;你需要支持你自己的代码。如果你不能,理解你给出的代码不要使用它或先了解它在做什么(或者你做错了事情)。

注意我使用自己的对象,在没有消耗性样本数据的情况下:

CREATE TABLE TableOfTables (TableName sysname,
                            NoOfDays int);
GO

INSERT INTO TableOfTables
VALUES ('T1',10),
       ('T2',15),
       ('T3',5);
GO


DECLARE Deletes CURSOR FOR
SELECT TableName, NoOfDays
FROM TableOfTables;

DECLARE @SQL nvarchar(MAX), @TableName sysname, @Days int;

OPEN Deletes;

FETCH NEXT FROM Deletes
INTO @TableName, @Days;

WHILE @@FETCH_STATUS = 0 BEGIN

    SET @SQL = N'DELETE FROM ' + QUOTENAME(@TableName) + NCHAR(10) +
               N'WHERE DATEDIFF(DAY, InsertedDate, GETDATE()) >= @dDays;'
    PRINT @SQL; --Say hello to your best friend. o/
    --EXEC sp_executeSQL @SQL, N'@dDays int', @dDays = @Days; --Uncomment to run

    FETCH NEXT FROM Deletes
    INTO @TableName, @Days;
END

CLOSE Deletes;
DEALLOCATE Deletes;    

GO
DROP TABLE TableOfTables;
GO

【讨论】:

    猜你喜欢
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 2013-07-13
    • 2020-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多