我有一个应用程序通过查询远程API执行大量搜索。结果将被拉入我的数据层(SQL Server),用于查看用户是否希望进一步与它们进行交互。一旦用户开始使用该项目,它必须保留在系统中,但其余结果完全没用,只占用空间。
我正在考虑创建一个运行sproc的任务来删除任何未被另一个表引用的行。有没有办法做到这一点?
另一种措辞方式是:是否有办法执行一个删除语句,该语句会跳过因违反参照完整性而导致错误的行?
编辑:感谢来自@Kos的新信息...... 我正在考虑的备用路径是向表中添加一个位列,如果该行最终被使用并将我的任务删除行标记为false,则将其标记为true。
为清楚起见,以下是对情况的概述。这些语法可能并不完美,但希望你能得到这个想法:
-- 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]
答案 0 :(得分:4)
您也可以使用此查询,使用join而不是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
答案 1 :(得分:2)
我今天遇到了同样的问题并最终到了这里。最终我提出了一种不同的方法,更接近劳伦斯寻找IMO的方法,但也可能慢得多,这在我自己的情况下不是问题。
所以基本上我使用游标逐个删除我的行,并且如果发生约束错误,我将delete语句放在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
答案 2 :(得分: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中的一个标志,表示该行正在数据库中的“某处”引用。我看到这种方法的缺点是,如果引用可以在以后消失,那么维护标志会变得更难。
答案 3 :(得分:1)
检查link。这将帮助您获取数据库中的所有外键关系。那里给出的脚本可以只过滤你需要的表格
获得列表后,可以将其转储到临时表中。该表将具有表名和列名,它们之间具有FK关系。然后你必须循环遍历这个表的每个记录并使用动态查询(因为表和列名称将出现在行中),你将不得不在Dump表中找到FK关系中的记录并转储到另一个临时表中。最后删除转储表中所有在此临时表中NOT EXIST
的记录
试一试。希望它有所帮助!!
答案 4 :(得分:1)
我最终得到的解决方案类似于@Kos对OP评论中的建议。它有点自然,因为我意识到如果用户交互,这个表的性质至少需要一个引用另一个表的外键,所以类似于BIT列,我只是运行这样的语句:
DELETE FROM [table] WHERE ISNULL([colForeignKey], 0) = 0
对于其他访问者,我建议查看@Maryam的答案,因为我认为大多数登陆此页面的人都是最好的解决方案(至少在发布时已经给出了)。
感谢大家的帮助