как использовать выберите в, чтобы вставить много записей - PullRequest
1 голос
/ 16 мая 2019

У меня есть хранимая процедура, которая будет копировать данные из таблицы A в таблицу B и возвращать идентификатор, сгенерированный из таблицы B, чтобы обновить запись таблицы. это пример данных таблица А:

id----Name---refId---value----KPI 
 1    ahmed    550    50      30
 2    ali             30 
 3    soo      561    40      30

Таблица B:

Id ---- Name ---- Value
550     ahmed       50
561     soo         30

я пробовал следующее я определил тип записи

VAR_RECORD_A mySchema.A%rowtype;
refffId Number ;
BEGIN
select 
* 
into
VAR_RECORD_A 
from mySchema.A
where (value passed to function)=  var_kpi_element_req.BPM_KPI_ID ;
end ;
begin
insert into mySchema.B
(name , value)
Values 
(VAR_RECORD_A.name , VAR_RECORD_A.value)
RETURNING Id into refffId ;
end;

begin 
update A 
set refId = refffId 
where kpi =(value passed to function)
end;

моя проблема в том, что выбор в возвращает много записей, я верю, что мой код будет работать, если вернет только 1 запись

Ответы [ 2 ]

1 голос
/ 16 мая 2019

Самое простое решение - использовать цикл Cursor:

    -- don't declare VAR_RECORD_A as rowtype ... 
    refffId Number ;
BEGIN
    for VAR_RECORD_A in ( -- instead make it a cursor ref 
        select * 
        from mySchema.A
        where (value passed to function)=  var_kpi_element_req.BPM_KPI_ID    
  ) 
  loop

    insert into mySchema.B
    (name , value)
    Values 
    (VAR_RECORD_A.name , VAR_RECORD_A.value)
    RETURNING Id into refffId ;

    update A 
    set refId = refffId 
    where kpi =(value passed to function)
    and a.PK = VAR_RECORD_A.pk -- identify current row of A for update

  end loop;

Примечание. Я удалил ненужные обозначения BEGIN… END.Вложенные блоки объявляйте только тогда, когда в этом есть реальная ценность.

В реальной жизни я бы хотел сделать эту массовую операцию более эффективной, используя коллекции и операторы forall для подхода на основе множеств.

Кроме того, я бы подумал, нужно ли мне блокировать выбранные строки из A ДЛЯ ОБНОВЛЕНИЯ KPI, в случае, если вся моя транзакция не удалась из-за другого сеанса, имеющего блокировку для одной строки.Это позволит вам использовать синтаксис WHERE CURRENT OF при обновлении A.

0 голосов
/ 16 мая 2019

Думаю, так будет лучше ...

DECLARE @VarA TABLE
	(

	id INT IDENTITY(1,1) PRIMARY KEY,
	Name nVARCHAR(100),
	refId INT,
	value INT,
	KPI INT
	)

DECLARE @VarB TABLE
	(
	id INT IDENTITY(5,1) PRIMARY KEY,
	Name nVARCHAR(100),
	value INT
	)

DECLARE @output TABLE
	(
		id INT,
		Name nVARCHAR(100)
	)

INSERT INTO @VarA
(Name, refId, value, KPI)
VALUES
('ahmed',550,50,  30),
('ali', NULL, 30, NULL),
('soo',  561,40,  30)

INSERT INTO @VarB
(Name, value)
VALUES
('ahmed', 50),
('soo', 30)

MERGE INTO @VarB AS Target  
USING (SELECT Name, Value FROM @VarA) AS Source (Name, Value)  
ON Target.Name = Source.Name  
WHEN MATCHED THEN  
	UPDATE SET Value = Source.Value --Do you want to update the value if record exists? 
WHEN NOT MATCHED BY TARGET THEN  
	INSERT (Name, Value) VALUES (Name, Value)  
OUTPUT inserted.ID, inserted.Name INTO @output(ID, Name);

UPDATE a SET refId = o.ID FROM @VarA a
INNER JOIN @output o ON o.Name = a.Name

SELECT * FROM @VarA
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...