生成删除查询

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 而它没有打印

以上是关于生成删除查询的主要内容,如果未能解决你的问题,请参考以下文章

在 Laravel 4 查询生成器中使用 Join 删除

当我在 c# 中显示从查询生成的 SQL 时,最后一部分是啥?我可以删除它吗?

第121天学习打卡(MyBatisPlus CRUD扩展之查询操作 分页查询 删除操作 逻辑删除 条件构造器 自动生成器 )

我用Sqlserver2008查询时生成的Sql语句,都是自动换行的,如何设置可以不换行?

MybatisPlus实现基本CURD&逻辑删除&代码生成(对标Django系列学习二)

mysql中使用@变量名:=值 生成的变量如何查看和删除?