如何使用select插入许多记录

时间:2019-05-16 09:15:54

标签: sql oracle plsql

我有一个存储过程,它将存储数据从表A复制到表B,并返回从表B生成的ID以更新表记录。 这是样本数据 表A是:

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;

我的问题是select into将返回许多记录,我相信我的代码仅返回1条记录就可以工作

2 个答案:

答案 0 :(得分:1)

最简单的解决方案是使用游标循环:

    -- 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更新,以防我的整个事务由于另一会话锁定一行而失败。这样做可以使您在更新A时使用WHERE CURRENT OF语法。

答案 1 :(得分:-1)

认为这样会更好...

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