【问题标题】:Deleting from multiple tables in SQL older than x amount of days从 SQL 中超过 x 天的多个表中删除
【发布时间】:2019-09-13 17:54:36
【问题描述】:

这是我的情况。我们这里有一个数据库,其中只有一堆日志记录。我们有一个单一的作业设置来清除该表上超过 30 天的日志中的任何内容……这很容易设置。

所以我的问题是,现在他们需要某种脚本或存储过程来删除该数据库中所有表中超过 30 天的所有内容。你知道有什么可以做到这一点吗?我已经在网上搜索了几个小时,查看存储过程和查询并没有真正到达任何地方。我创建了一个查询,该查询单独对该数据库中的所有表执行此操作,但是当他们向该数据库添加和删除表时,他们想要更动态的东西,这样我们就不必继续编辑查询。

所以这将是一个存储过程,基本上会对数据库中的所有表执行此操作

USE TESTLog;

delete FROM TestLogTable WHERE Date < GETDATE() – 30

有什么想法可以做到这一点吗?

更新: 因此,我与她推荐使用存储过程(如下)的朋友交谈,但我似乎无法让 exec 与删除一起运行。打印效果很好。但是当我更改为 EXEC (SQL) 时它不起作用。

USE [TEST_DELETE]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

--Creates stored procedure
ALTER PROCEDURE [dbo].[TableCleanup]
AS
    --Code starts here for table cleanup--
    DECLARE @myCursor cursor;
    DECLARE @tableName CHAR(100),
            @sql CHAR(300)

BEGIN
    SET @myCursor = CURSOR FOR
        SELECT rtrim(table_schema) + '.' + rtrim(Table_Name) as tableName
        FROM information_schema.tables Where table_type = 'Base Table'

  OPEN @myCursor

  FETCH NEXT FROM @myCursor INTO @tableName

  WHILE @@FETCH_STATUS = 0
  BEGIN
      SET @sql = 'delete FROM ' + rtrim(@tableName )+ ' WHERE Date < GETDATE() – 30'
      EXEC (@sql)

      FETCH NEXT FROM @myCursor INTO @tableName             
  END   

  CLOSE @myCursor
  DEALLOCATE @myCursor
END

【问题讨论】:

  • 盲目地对数据库中的每个表执行此操作似乎是一个非常糟糕的主意。您在每个表中都有该列吗?查找表呢? RI呢?您必须在父行之前删除子行。
  • 他们要删除的是所有表中的 DATE COLUMN。我不知道为什么,他们只是想这样做。大多数表都有 DATE 列,但少数有 STARTDATE 和 ENDDATE,他们说他们不关心这些表……只关心那些具有 DATE 列的表。
  • 不能删除列,只能删除行。是否要将 DATE 列设置为 NULL?您将不得不查询 sys.columns 并找到具有所需列名的表,然后针对这些表运行查询。
  • 抱歉你是对的,这就是我的意思...行而不是列。

标签: sql sql-server


【解决方案1】:

试试这个,假设 Date 字段存在于该数据库的所有表中

USE TESTLog;
GO
EXEC sp_MSForEachTable 'DELETE FROM ? WHERE [Date] < GETDATE() - 30'
GO

【讨论】:

  • 我试过这个,但得到 Msg 102, Level 15, State 1, Line 1 '-' 附近的语法错误。
  • Msg 207, Level 16, State 1, Line 1 列名“日期”无效。
  • 上述消息是否来自没有 DATE 列的表?
  • 那是因为 Date 是一个保留字(可怕的列名)。您必须将其括在方括号中。 [日期]
  • 我绝对不会和你争论这个。我没有设计这个数据库,它是一团糟......我正在尽我所能用我必须使用的东西。当试图告诉一个由 10 到 12 名开发人员组成的团队如何创建这些数据库时,这是一个敏感的话题。
【解决方案2】:

查询所有表名的master。然后将表名应用于您的 SQL

【讨论】:

  • 嗯,这就是我认为我可以做的......这样的事情......但还没有奏效或还没有成功。使用测试删除; SELECT * FROM information_schema.tables WHERE Date
【解决方案3】:

您需要查询 sys.columns 以确定哪些表具有名为 Date 的列。这将为您生成删除语句。我会使用一些东西将其生成为一个列表,然后使用 sp_executesql 执行整个操作。

declare @SQL nvarchar(max) = ''

select @SQL = @SQL + 'delete from [' + OBJECT_NAME(OBJECT_ID) + '] where [Date] < DATEADD(DAY, -30, GETDATE());'
from sys.columns
where name = 'Date'

select @SQL
exec sp_executesql @SQL

【讨论】:

  • 好的,这样查询就产生了我正在寻找的具有这些列/行的表的结果。我会怎么做,将 sp_executesql 添加到查询的末尾?
  • @jcosley 我编辑了答案以包含执行此操作的代码。
  • 我刚刚尝试过,但没有成功,给了我 Msg 102, Level 15, State 1, Line 1 'exec' 附近的语法错误
  • 注释掉 exec 并检查 @SQL 的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多