生成删除查询
Posted
技术标签:
【中文标题】生成删除查询【英文标题】:generates the Delete query 【发布时间】:2020-11-03 01:56:41 【问题描述】:我正在尝试编写一个查询,它会根据要求自动。我会从不同的表中删除数据并转储到临时表中,然后使用这个临时表我需要使用 IN 运算符编写查询,请建议我,这是我尝试过的。
SET NOCOUNT ON
DECLARE @DeleteDisbursement TABLE (DisbursementId BIGINT, PolicyNumber NVARCHAR(10),DisbursementAmount DECIMAL(19,4))
DECLARE @DeleteRecords Table(DisbursementId BIGINT,ActivityId BIGINT)
INSERT INTO @DeleteDisbursement (DisbursementId,PolicyNumber,DisbursementAmount)
VALUES
(4576,'12345',3.00),
(1232,'65455',143.44),
(2341,'34234',228.95),
(1111,'23155',414.89)
SELECT * from @DeleteDisbursement
DECLARE @GenerateScriptCount BIGINT =0
DECLARE @DisbursementIDValue BIGINT =0
DECLARE @ActivityIdValue BIGINT =0
WHILE EXISTS(SELECT Top 1 1 FROM @DeleteDisbursement)
BEGIN
DECLARE @DisbursementId BIGINT =0
DECLARE @PolicyNumber NVARCHAR(10)
DECLARE @AccountId BIGINT =0
DECLARE @ActivityId BIGINT
DECLARE @DisbursementAmount DECIMAL(19,4)
SELECT TOP 1 @DisbursementId =DisbursementId ,@PolicyNumber = PolicyNumber,@DisbursementAmount = DisbursementAmount
FROM @DeleteDisbursement
SET @ActivityId = (SELECT ActivityId FROM ActivityLog WHERE ActivityAmount = @DisbursementAmount)
IF (@ActivityId > 0)
BEGIN
INSERT INTO @DeleteRecords (DisbursementId,ActivityId) VALUES(@DisbursementId,@ActivityId)
END
DELETE FROM @DeleteDisbursement WHERE DisbursementId = @DisbursementId
END
WHILE EXISTS(SELECT Top 1 1 FROM @DeleteRecords)
BEGIN
SELECT TOP 1 @DisbursementIDValue= @DisbursementId,@ActivityIdValue = @ActivityId FROM @DeleteRecords
PRINT 'DELETE FROM Disbursement Where DisbursementId IN (' + CONVERT(NVARCHAR(MAX), @DisbursementIDValue) +')'
PRINT 'DELETE FROM ActivityLog WHERE ActivityId IN (' + CONVERT(NVARCHAR(MAX), @ActivityIdValue) +')'
DELETE FROM @DeleteRecords WHERE DisbursementId = @DisbursementId
END
SET NOCOUNT OFF;
但它不起作用,请帮助我如何编写查询仅包含在 IN 运算符中的 1 个查询,如下所示:-
DELETE FROM Disbursement Where DisbursementId IN (4576,1232,2341,1111)
DELETE FROM ActivityLog WHERE ActivityId IN (1000,2000,3000,4000)
【问题讨论】:
您是否有理由要逐行执行此操作,而不仅仅是单个语句?有点不清楚您的@tables 是否仅用于演示目的,或者它们是否是您实际工作中的硬表。 我想我正在努力实现 - 我已经创建了 Temp 表,在该表中我已经插入了我想要根据 INPUT 值删除的所有记录(输入可能是 1000 条记录或更多) .现在使用这个临时表我必须使用 IN 运算符动态,例如 (Delete * from table1 where disbId IN(1,2,3,4,5,6 etc until 1000 rows)) ,这基本上是出于性能目的,我可以使用 = like (Delete * from table1 where disbId =1, Delete * from table1 where disbId =2 etc..) 来实现,但是它在 Prod 中需要很长时间,所以我必须只使用 IN跨度> 所以我的查询将只是手动执行打印操作,因此我将复制打印生成的查询并将放置到生产中以用于删除目的 请建议我如何在上述条件下进行 PRINT,我需要使用 IN 运算符打印所有需要删除的值,例如 PRINT ' DELETE FROM Disbursement Where DisbursementId IN (DisbursementIDValue)' 【参考方案1】:我知道这不是在回答您的直接问题,但我很确定它会更快并避免您的任何问题。毫无疑问,您必须进行调整以匹配您的实际版本,但这应该会给出想法。
begin transaction
delete Disbursement
from DeleteDisbursement dd
join Disbursement on Disbursement.DisbursementId=dd.DisbursementId
delete ActivityLog
from DeleteDisbursement dd
join ActivityLog on ActivityLog.ActivityAmount=dd.DisbursementAmount
commit work
【讨论】:
谢谢汤姆,基本上我的要求不是像这样直接删除,我需要打印动态生成的查询,比如 - PRINT ' DELETE FROM Disbursement Where DisbursementId IN (DisbursementIDValue)' ,这里的 DisbursementIDValue 可能是这样的1,2,3,4,5等..它应该动态生成,我不明白如何做到这一点【参考方案2】:您不需要这么复杂。您首先将值存储在临时表中,然后将临时表重用于您的删除语句。或者您可以使用 STRING_AGG 函数生成 id 列表(从 SQL 2017 开始支持)。
DECLARE @sqlStmt NVARCHAR(MAX) = '
CREATE TABLE #DeleteDisbursement (DisbursementId BIGINT, PolicyNumber NVARCHAR(10),DisbursementAmount DECIMAL(19,4))
CREATE TABLE #DeleteRecords (DisbursementId BIGINT,ActivityId BIGINT)
INSERT INTO #DeleteDisbursement (DisbursementId,PolicyNumber,DisbursementAmount)
VALUES
(4576,'12345',3.00),
(1232,'65455',143.44),
(2341,'34234',228.95),
(1111,'23155',414.89)
INSERT INTO #DeleteRecords (DisbursementId,ActivityId)
SELECT DisbursementId , ActivityId FROM ActivityLog AS al
INNER JOIN #DeleteDisbursement AS dd
ON dd.DisbursementAmount = al.ActivityAmount
'
方法 1(使用 Temp 表作为 Id 列表)
SET @sqlStmt += '
DELETE FROM Disbursement Where DisbursementId IN (SELECT
DisbursementId FROM #DeleteRecords)
DELETE FROM ActivityLog WHERE ActivityId IN (SELECT
ActivityId FROM #DeleteRecords)'
PRINT @sqlStmt
方法 2(使用 STRING_AGG 生成 Id 列表)
SET @sqlStmt += '
DELETE FROM Disbursement Where DisbursementId IN (' + SELECT STRING_AGG(DisbursementId ,',') FROM #DeleteRecords + ');'+ CHAR(13) + CHAR(10) + 'GO' + CHAR(13) + CHAR(10) +
'DELETE FROM ActivityLog WHERE ActivityId IN (' + SELECT
STRING_AGG(ActivityId ,',') FROM #DeleteRecords+ ');'+ CHAR(13) + CHAR(10) + 'GO'
PRINT @sqlstmt
【讨论】:
感谢 venkat 的回复,我尝试了您的方法,但它对我不起作用,因为在我的情况下,我必须循环使用 while 语句插入到 @DeleteRecords 表中,因为我将获得基于 ActivityId如我上面的查询所示,在不同的条件下。我已经尝试在里面添加你的方法 1 而它没有打印以上是关于生成删除查询的主要内容,如果未能解决你的问题,请参考以下文章
当我在 c# 中显示从查询生成的 SQL 时,最后一部分是啥?我可以删除它吗?
第121天学习打卡(MyBatisPlus CRUD扩展之查询操作 分页查询 删除操作 逻辑删除 条件构造器 自动生成器 )
我用Sqlserver2008查询时生成的Sql语句,都是自动换行的,如何设置可以不换行?