#sql #sql-server #transactions
#sql #sql-сервер #транзакции
Вопрос:
Я создал хранимую процедуру (пожалуйста, игнорируйте синтаксические ошибки)
alter proc usp_newServerDetails
(@appid int, @envid int, @serType varchar(20), @servName varchar(20))
as
declare @oTbl_sd table (ID int)
declare @outID1
declare @oTbl_cd table (ID int)
declare @outID2
begin Transaction
insert into server_details(envid, servertype, servername)
output inserted.serverid into @oTbl_sd(ID)
values(@envid, @serType, @servName)
select @outID1 = ID from @oTbl_sd
insert into configdetails(serverid, servertype, configpath, configtype)
output inserted.configid into @oTbl_cd(ID)
(select @outID1, cm.servertype, cm.configpath, cm.configtype
from configpthmaster cm
where cm.appid = @appid )
select @outID2 = ID from @oTbl_cd
insert into configkeydetails(confiid, keyname)
output inserted.Keyid into @oTbl_ckd(ID)
(select @outID2, cm.key
from configpthmaster cm
where cm.appid = @appid)
begin
commit
end
server_details
таблица имеет столбец identity ID
с автоматически созданным ie. @outID1
и первый запрос insert вставляет только 1 строку.
configpthmaster
таблица не связана напрямую с какой-либо другой таблицей и содержит 2 уникальные строки данных, которые я хочу извлечь для вставки данных в другие таблицы, одну за другой во время вставки.
Второй запрос insert извлекает данные из configpthmaster
таблицы и вставляет 2 строки во configdetails
время генерации (автоматически сгенерированного) идентификатора @outID2
, т.Е. .
Он также имеет FK, сопоставленный с server_details
.
Проблема в том, что «@outID2» выдает только последний вставленный идентификатор (т.Е. если два идентификатора сгенерированы 100,101, я получаю 101), что в конечном итоге при 3-й вставке вставляет 2 строки только с тем же идентификатором 101, но я хочу, чтобы вставка была линейной. т.е. Одна для 100, а другая для 101.
Если при вставке были затронуты нулевые строки, как откатить транзакцию?
Как я могу выполнить эти требования? Пожалуйста, помогите.
Ответ №1:
Измените свою процедуру, как показано ниже, и повторите попытку.
ALTER PROCEDURE usp_newServerDetails(@appid int, @envid int,@serType varchar(20),@servName varchar(20))
AS
BEGIN
BEGIN TRY
DECLARE @Output TABLE (ID int,TableName VARCHAR(50),cmKey VARCHAR(50)) --table variable for keeping Inserted ID's
BEGIN TRAN
IF EXISTS ( SELECT 1 FROM configpthmaster cm WHERE cm.appid = @appid )
AND ( SELECT 1 FROM configkeydetails ck WHERE ck.appid = @appid ) --add a conditon to satisfy the valid insertions
BEGIN
INSERT INTO server_detials(envid,servertype,servername)
OUTPUT inserted.serverid,'server_detials',NULL INTO @Output(ID,TableName,cmKey )
VALUES(@envid ,@serType ,@servName)
INSERT INTO configdetails(serverid,servertype,configpath,configtype)
OUTPUT inserted.configid,'configdetails',cm.Key INTO @Output(ID,TableName,cmKey )
SELECT t.ID,cm.servertype,cm.configpath,cm.configtype
FROM configpthmaster cm
CROSS APPLY (SELECT ID FROM @Output WHERE TableName='server_detials')t
WHERE cm.appid = @appid
INSERT INTO configkeydetails(configId,keyname)
SELECT ID,cmKey FROM @Output
WHERE TableName='configdetails'
END
COMMIT TRAN
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK
END CATCH
END
Комментарии:
1. Спасибо, но теперь, когда при 3-й вставке в configkeydetails в результате будет затронута строка 0: (я хочу, чтобы идентификатор, сгенерированный во 2-й вставке, использовался в 3-й, и соответствующее значение должно быть сохранено. @UnnikrishnanR
2. @ManojKargeti Я думаю, что это будет работать таким же образом. Он проверит, есть ли какие-либо записи в таблицах configpthmaster и configkeydetails с заданным appid , только после этого он начнет заполнять данные. для вставки в configkeydetails детали будут принимать вставленный configid из второй вставки.
3. Я выполнил предоставленный вами код, но в результате в 0 затронутых строках вставка в последние две таблицы выполняется один к одному, но с использованием «ПЕРЕКРЕСТНОГО ПРИМЕНЕНИЯ» для 2 записи в configpthmaster «ВЫБЕРИТЕ t.ID ,см.[ключ] ИЗ configpthmaster cm ПЕРЕКРЕСТНО ПРИМЕНИТЬ (ВЫБЕРИТЕ ИДЕНТИФИКАТОР ИЗ вывода, ГДЕ TableName=’configdetails’)t ГДЕ cm.appid = appid » дает 4 набора результатов @UnnikrishnanR
4. Будет две записи, если в configpthmaster есть два значения, соответствующие заданному @appid . Скажем, если config master повторно использует значения 2 и 3, соответствующие givan AppID, вторая вставка будет содержать две строки, соответствующие вставленным server_detials в первой таблице вставки server_detials.
5. Нет, пожалуйста, смотрите, ВЫБЕРИТЕ t.ID ,cm.[ключ] ИЗ configpthmaster cm ПЕРЕКРЕСТНОЕ ПРИМЕНЕНИЕ (ВЫБЕРИТЕ ИДЕНТИФИКАТОР ИЗ вывода, ГДЕ TableName=’configdetails’)t, ГДЕ cm.appid = appid ** допустим, ВЫБЕРИТЕ ИДЕНТИФИКАТОР ИЗ вывода, ГДЕ TableName=’configdetails’ дает 100,102, а configpthmaster имеет 2 строки сappid 143 и ключ x и appid 143 и ключ y ** ВЫБЕРИТЕ t.ID ,см.[ключ] даст 100 143 x и 100 143 y , 102 143 x и 102 143 y ???? @UnnikrishnanR
Ответ №2:
Не могли бы вы попробовать это решение?
alter proc usp_newServerDetails(@appid int, @envid int,@serType varchar(20),@servName varchar(20))
as
declare @oTbl_sd table (ID int)
declare @outID1
declare @oTbl_cd table (ID int)
declare @outID2
begin Transaction
insert into server_detials(envid,servertype,servername)
output inserted.serverid into @oTbl_sd(ID)
values(@envid ,@serType ,@servName)
select @outID1 = ID from @oTbl_sd
insert into configdetails(serverid,servertype,configpath,configtype)
output inserted.configid into @oTbl_cd(ID)
(select @outID1 ,cm.servertype,cm.configpath,cm.configtype from configpthmaster cm where cm.appid = @appid )
select @outID2 = ID from @oTbl_cd
insert into configkeydetails(confiid,keyname)
output inserted.Keyid into @oTbl_ckd(ID)
(select isnull(replace(stuff((SELECT inserted.configid FOR xml path('')), 1, 1, ''), 'amp;amp;', 'amp;'), '') ,cm.key, from configpthmaster cm where cm.appid = @appid )
begin
commit
end
Я только что добавил МАТЕРИАЛ в ваш код.
Функция STUFF вставляет строку в другую строку.
Обратите внимание, что использование STUFF значительно замедляет время обработки кода.
для получения дополнительной информации о материалах