Sql server 删除了周围的约束
我必须创建一个SQL query.SQL文件,由SQLServer中的sqlcmd.exe运行,以删除特定天数内的所有记录。然而,我发现自己被如何绕过外键约束所迷惑。为了说明问题,这里有三个具有类似关系的表。请注意,这是伪代码:Sql server 删除了周围的约束,sql-server,tsql,Sql Server,Tsql,我必须创建一个SQL query.SQL文件,由SQLServer中的sqlcmd.exe运行,以删除特定天数内的所有记录。然而,我发现自己被如何绕过外键约束所迷惑。为了说明问题,这里有三个具有类似关系的表。请注意,这是伪代码: CREATE TABLE runlog( row_id int identity(1,1) NOT NULL, run_id nvarchar(25) NULL FOREIGN KEY REFERENCES status(run_id), mas
CREATE TABLE runlog(
row_id int identity(1,1) NOT NULL,
run_id nvarchar(25) NULL FOREIGN KEY REFERENCES status(run_id),
master_id nvarchar(25) NULL FOREIGN KEY REFERENCES master(master_id),
)
CREATE TABLE status(
run_id nvarchar(25) NOT NULL,
master_id nvarchar(25) NULL FOREIGN KEY REFERENCES master(master_id),
status_date datetime NULL,
)
CREATE TABLE master(
master_id nvarchar(25) NOT NULL,
)
通常情况下,删除是按照runlog、status、master的顺序进行的,但我需要确定记录的保存时间的字段在status表中。因此,我不能在主表之前从状态表中逻辑删除,但我也不能以另一种方式进行删除。
对于运行日志表,我可以使用以下内容:
delete from runlog
inner join status on status.run_id = runlog.run_id
where status.status_date <= DATEADD(DAY, -30, GETDATE())
要选择所需的主id,我可以使用:
select master_id from status
where status.status_date <= DATEADD(DAY, -30, GETDATE())
然后,如果有一种方法可以缓存这个列表,我可以使用它从status中删除列表,然后从master中删除列表,但如果没有新的存储过程,我不知道如何执行此操作。有什么建议吗 您可以在delete语句中使用output子句将删除的数据插入到表变量中 这将允许您按照需要的顺序执行删除操作。。这假设run_id是Status的主键,master_id是master的主键
BEGIN TRANSACTION;
BEGIN TRY
declare @runIds Table (id nvarchar(25))
declare @masterIds Table (id nvarchar(25))
delete rl
OUTPUT DELETED.run_id into @runids
from runlog as rl
inner join StatusTbl on StatusTbl.run_id = rl.run_id
where StatusTbl.status_date <= DATEADD(DAY, -30, GETDATE())
delete from StatusTbl
OUTPUT DELETED.master_id into @masterIds
where run_id in (select id from @runIds)
delete from MasterTbl
where master_id in (select id from @masterIds)
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
GO
编辑
我意识到您的场景纯粹是假设的,但是您也可以使用合并来进行连接删除,我很确定这比执行连接样式更新/删除更值得推荐。此外,我发现编写合并语句给我带来了很多乐趣:-
MERGE runlog AS target
USING (select run_id, status_date FROM StatusTbl where StatusTbl.status_date <= DATEADD(DAY, -30, GETDATE())) AS source ([run_id], [status_date])
ON (target.run_id = source.[run_id])
WHEN MATCHED THEN DELETE
OUTPUT DELETED.run_id into @runids;
如何使用master_id删除主表中状态不匹配的所有记录?这样就不需要缓存状态表的记录,这是一个想法。但我不想错误地删除一些原本不应该删除的东西。从技术上讲,在主记录的状态存在之前,可以在主记录中创建记录。确实,您可以将statusmaster\u id中的外键更改为级联删除。因此,当您删除master中的记录时,它将删除状态中的记录。我想我需要创建一个临时表来保存master_id结果,然后与该表连接以执行删除,然后删除该表。。。但是,我不认为运行脚本的用户可以创建table为什么不能首先将要删除的记录列表缓存到表变量/temp表中?