【问题标题】:How to use loop to insert records of data into table?如何使用循环将数据记录插入表中?
【发布时间】:2018-12-23 08:21:32
【问题描述】:

我想使用 PL/SQL 循环插入几条记录,但是当我在 SQL Developer 中执行以下块时,我收到以下错误:

declare
    loop_size number;

begin
    loop_size := 10;

    while loop_size > 0
    loop
        INSERT INTO CM.CUSTOMER (ID, FIRST_NAME, LAST_NAME, STATUS )
        VALUES (CM.SQ_CUSTOMER.nextval, 'Jhon', 'Jhon',10);

        loop_size := loop_size -1;      
    end loop;
end; 

错误

PLS-00225: subprogram or cursor 'CM' reference is out of scope

【问题讨论】:

  • 你认为CM 是什么?架构?哪个用户运行这个?
  • 是的,它是架构。
  • 那么你会以另一个用户的身份运行它吗?通常最好不要硬编码模式名称,除非你真的必须这样做。我宁愿省略模式名称并从CM 帐户运行它。 (顺便说一句,你有一个status 变量,但你不使用它。它是刺还是数字?)

标签: oracle plsql sql-insert


【解决方案1】:

我无法重现您的错误,但一个问题是CM.CUSTOMER 不能既是表又是序列。

通常最好不要硬编码模式名称,除非你真的必须这样做。我宁愿在这里省略模式名称,只从CM 帐户运行它。

我创建了一个名为 customer_seq 的序列,并且以下运行没有错误:

create table customer
( id          number primary key 
, first_name  varchar2(20)
, last_name   varchar2(20)
, status      number );

create sequence customer_seq;

declare
    status varchar(10) := '10';
    loop_size number := 10;
begin
    while loop_size > 0
    loop
        insert into customer (id, first_name, last_name, status)
        values (customer_seq.nextval, 'Jhon', 'Jhon', status);

        loop_size := loop_size -1;      
    end loop;
end;
/

如果使用 Oracle 12.1 或更高版本,我更愿意使用标识列并停止微管理序列。您也不需要自己管理循环索引,因为 PL/SQL 有一个方便的 for 循环结构:

create table customer
( id          number generated always as identity primary key 
, first_name  varchar2(20)
, last_name   varchar2(20)
, status      number );

declare
    status varchar(10) := '10';
    loop_size number := 10;
begin
    for i in 1..loop_size loop
        insert into customer (first_name, last_name, status )
        values ('Jhon', 'Jhon', status);
    end loop;
end;
/

【讨论】:

  • OP 使用CM.CUSTOMER 作为表名和序列名的好地方。
【解决方案2】:

您可以在没有动态 SQL 的情况下实现这一点:

INSERT INTO CM.CUSTOMER (FIRST_NAME, LAST_NAME, STATUS)
SELECT 'Jhon', 'Jhon', '10'
FROM dual
CONNECT BY rownum <= 10;

这个答案假定ID 列是自动递增的,它可能应该是。

【讨论】:

  • 嗯,在STATUS的OP版本值中是10
【解决方案3】:

删除最后一个不必要的逗号并从对偶中选择序列:

  INSERT INTO CM.CUSTOMER (ID, FIRST_NAME, LAST_NAME, STATUS)
  select ln.SQ_CUSTOMER, 'Jhon', 'Jhon', 10 from dual;

将序列更新为ln.SQ_CUSTOMER

【讨论】:

  • 那不行,要么删除 VALUES,要么删除 SELECT & FROM DUAL。
  • 另外CM.CUSTOMER 不能既是表又是序列。
  • @user7294900 似乎无法识别架构ln,我收到以下错误:PLS-00225: subprogram or cursor 'LN' reference is out of scope
【解决方案4】:

非常感谢您的回复,我终于解决了我的问题如下:

declare
loop_size number;
rec_id NUMBER;

begin
  loop_size := 10;

  while loop_size > 0
  loop

    execute immediate 'select cm.SQ_CUSTOMER.nextval from dual' into rec_id;

    INSERT INTO CM.CUSTOMER (ID, FIRST_NAME, LAST_NAME, STATUS )
    VALUES (rec_id, 'Jhon', 'Jhon',10);

    loop_size := loop_size -1;      
  end loop;
end; 

【讨论】:

  • 在不使用execute immediate的情况下查看我的更新答案
  • 你为什么要使用execute immediate (pre-12c 风格)序列? (为什么它与表的模式不同?)您可以像分配其他变量一样分配它:rec_id := sq_customer.nextval。或者更好的是,直接在insert 语句中使用它,不需要任何中间变量。或者更好的是,使用身份列并忘记序列(请参阅我的答案)。
猜你喜欢
  • 2017-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 2016-08-17
  • 2017-09-30
相关资源
最近更新 更多