генерирует запрос на удаление

#sql #.net #sql-server

#sql #.net #sql-сервер

Вопрос:

Я пытаюсь написать запрос, который автоматически генерирует запрос на удаление на основе требований. Я получу удаляемые данные из разных таблиц и дамп во временную таблицу, а затем, используя эту временную таблицу, мне нужно написать запрос, используя оператор 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;
  

Но он не работает, пожалуйста, помогите мне, как мне написать запрос только на 1 запрос, который включен в оператор IN, как показано ниже :-

 DELETE FROM Disbursement Where DisbursementId IN (4576,1232,2341,1111)
DELETE FROM ActivityLog WHERE ActivityId IN (1000,2000,3000,4000)
  

Комментарии:

1. Есть ли причина, по которой вы хотите выполнять это строка за строкой, а не только один оператор? Немного неясно, предназначены ли ваши @tables только для демонстрационных целей или это жесткие таблицы в вашей реальной работе.

2. Я хочу, чтобы я пытался достичь — я создал временную таблицу, в эту таблицу я вставил все записи, которые я хочу удалить, на основе входного значения (ввод может быть 1000 записей или более). Используя эту временную таблицу, теперь я должен динамически генерировать запрос на удаление с помощью оператора IN like (Удалить * из table1, где disbId IN(1,2,3,4,5,6 и т. Д. До 1000 строк)) , Это в основном для повышения производительности, я могу достичь, используя = like (Удалить * из table1, где disbId =1, удалить *из table1, где disbId = 2 и т. Д.), Но это занимает очень много времени в Prod, поэтому я должен использовать только в

3. Итак, мой запрос просто выполнит операцию печати, поэтому вручную я скопирую сгенерированный запрос на печать и отправлю в производство для удаления

4. Пожалуйста, подскажите мне, как мне выполнить ПЕЧАТЬ с моим вышеуказанным условием, мне нужно НАПЕЧАТАТЬ все значения, которые мне нужно удалить, используя В операторе, например, PRINT ‘ УДАЛИТЬ ИЗ выплаты, где используется идентификатор выплаты (значение выплаты)’

Ответ №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
  

Комментарии:

1. Спасибо, Том, в основном мое требование не заключается в удалении напрямую, как это, мне нужно НАПЕЧАТАТЬ динамически сгенерированный запрос типа — PRINT ‘ УДАЛИТЬ ИЗ выплаты, где DispensementId IN (DispensementIDValue)’, здесь DispensementIDValue может быть таким: 1,2,3,4,5 и т. Д. Он должен генерироваться динамически, я не понимаю, как это сделать

Ответ №2:

Вам не нужна такая сложность. Сначала вы сохраняете значения во временной таблице и повторно используете временную таблицу для своего оператора delete. или вы можете сгенерировать список идентификаторов с помощью функции STRING_AGG (поддерживается начиная с 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 (использование временной таблицы для списка идентификаторов)
 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)
 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
  

Комментарии:

1. Спасибо venkat за ваш ответ, я попробовал ваш подход, он не сработал для меня, потому что в моем случае мне приходится использовать оператор while для вставки в таблицу @DeleteRecords, потому что я получу ActivityId на основе другого условия, как показано в моем приведенном выше запросе. И я попытался добавить ваш подход 1 внутрь, пока он не печатался