3

我有一个通过查询远程 API 进行大量搜索的应用程序。结果被拉入我的数据层(SQL Server),他们坐在那里查看用户是否愿意与他们进一步交互。一旦用户开始使用该项目,它必须留在系统中,但其余结果完全没有用,只是占用空间。

我正在考虑创建一个任务,该任务将运行一个存储过程来删除任何未被另一个表引用的行。有没有办法做到这一点?

另一种措辞是:有没有办法执行删除语句,该语句会跳过由于违反参照完整性而导致错误的行?

编辑:感谢@Kos的新信息...我正在考虑的替代路径是在表中添加一个位列,如果该行最终被使用并且只是让我的任务删除标记为假的行,则将其标记为真。

为清楚起见,这里是对情况的概述。这些语法可能并不完美,但希望你能明白:

-- Where all the results get pulled down and held (The table I want to clean up every 2 hours or so)
CREATE TABLE [reservations].[DumpTable](
    [utypeID] [bigint] IDENTITY(1,1) NOT NULL
    -- Other columns
    CONSTRAINT [PK_UnitTypesFound] PRIMARY KEY CLUSTERED 
    (
        [utypeID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]


-- This is one of many other tables that might reference the dump table
CREATE TABLE [reservations].[OtherTables](
    [memberID]  INT NOT NULL,
    [utypeID]   BIGINT NOT NULL -- Need to Know if the dumptable is referenced here
    CONSTRAINT [PK_MemberUnitTypes] PRIMARY KEY CLUSTERED
    (
        [memberID],
        [utypeID]
    ) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,     ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [reservations].[OtherTables]  WITH CHECK ADD  CONSTRAINT [FK_OtherTable_DumpTable] FOREIGN KEY([utypeID])
    REFERENCES [reservations].[DumpTable] ([utypeID])

ALTER TABLE [reservations].[OtherTables] CHECK CONSTRAINT [FK_OtherTable_DumpTable]
4

5 回答 5

5

我今天遇到了同样的问题,最终来到了这里。最终我想出了一个不同的方法,更接近劳伦斯寻找 IMO 的方法,但也很可能慢得多,这在我自己的情况下不是问题。

所以基本上我使用游标来一一删除我的行,如果发生约束错误,我将删除语句放在 try/catch 块中以恢复循环:

DECLARE @idc as int
DECLARE Contact_Cursor CURSOR FOR
SELECT ID 
FROM ContactInfo;
OPEN Contact_Cursor;
FETCH NEXT FROM Contact_Cursor INTO @idc 
WHILE @@FETCH_STATUS = 0
  BEGIN
    begin try
      delete from ContactInfo where id = @idc;
      FETCH NEXT FROM Contact_Cursor INTO @idc 
    end try
    begin catch
      FETCH NEXT FROM Contact_Cursor INTO @idc 
    end catch
   END;
CLOSE Contact_Cursor;
DEALLOCATE Contact_Cursor;
GO
于 2014-10-06T14:54:33.877 回答
4

您也可以使用此查询,使用联接而不是 where 子句加快查询速度。

DELETE FROM DATA_TABLE 
FROM         DATA_TABLE LEFT OUTER JOIN
                      OTHERON DATA_TABLE.OTHER_TABLE_ID= OTHER.ID 
WHERE     (OTHER.ID IS NULL) and DATA_TABLE.SOME_TIMESTAMP < threshold_time
于 2012-10-03T06:23:24.427 回答
1

我最终采用了类似于@Kos 在 OP 评论中推荐的解决方案。这有点自然,因为我意识到如果与用户交互,该表的性质将需要至少一个引用另一个表的外键,因此类似于 BIT 列,我只是运行如下语句:

DELETE FROM [table] WHERE ISNULL([colForeignKey], 0) = 0

对于其他访问者,我建议查看@Maryam 的答案,因为我认为大多数登陆此页面的人,这将是最好的解决方案(至少在发帖时已经放弃了)。

感谢你的帮助

于 2012-10-03T23:42:12.197 回答
1

检查此链接。这将帮助您获取数据库中的所有外键关系。那里给出的脚本规定只过滤您需要的表。
获得列表后,您可以将其转储到临时表中。该表将具有表名和列名,它们之间具有 FK 关系。然后,您将不得不遍历该表的每条记录并使用动态查询(因为表和列名将出现在行中),您将必须在 Dump 表中找到 FK 关系中的记录并转储到另一个临时表中. 最后从您的 Dump 表中删除NOT EXIST在此临时表中执行的所有记录。
试一试。希望能帮助到你!!

于 2012-10-03T05:16:03.953 回答
1

您的问题在细节上有点稀疏,但假设表格看起来像:

DATA_TABLE
    OTHER_TABLE_ID    INTEGER
    SOME_TIMESTAMP    DATETIME

OTHER_TABLE
    ID                INTEGER

然后是一个基本的删除,如:

DELETE FROM DATA_TABLE dt WHERE dt.SOME_TIMESTAMP < threshold_time
  AND NOT EXISTS (SELECT 1 FROM OTHER TABLE WHERE ID = dt.OTHER_TABLE_ID;

应该做的伎俩。我假设您需要给用户一些时间来决定使用 DATA_TABLE 中的给定行。

更新:如果 OTHER_TABLE 不是一个特定的表,但可能是几个表中的任何一个,那么最好的选择可能是 DATA_TABLE 中的一个标志,表明该行在数据库中的“某处”被引用。我认为这种方法的缺点是,如果引用可以在以后消失,那么维护标志就会变得更加困难。

于 2012-10-03T04:36:33.633 回答