#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 внутрь, пока он не печатался