尝试将一个函数(填充序列号)放置到变量中,并在游标循环中使用该函数将其插入记录的每一行,但是将无效标识符错误地表示给v_refnr变量。 PL/SQL: ORA-00904: "V_REFNR": invalid identifier
。
我找到的最接近的参考文献是这个[1] Call a function in a cursor for loop
我的函数没有参数。我在游标中所做的select语句(包含其他列)在输出值时没有问题。我继续使用for循环遍历每条记录,然后插入参考号以测试其是否有效。
这是我到目前为止尝试过的代码
Declare
v_refnr number;
cursor c_book IS
--working select statement--
r_book c_book%ROWTYPE
begin
v_refnr := get_refnr; <-- function
for r_book in c_book loop
insert into some_tbl refnr
values v_refnr;
end loop;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Error insert record ' || SUBSTR(SQLERRM, 1, 250));
ROLLBACK;
end;
如果以上是有效代码,它将在空白表中插入值。
答案 0 :(得分:1)
执行插入操作不需要游标循环。只需执行INSERT INTO SELECT *
,它比循环要有效得多。
因此,如果您想每次都调用该函数,请在select
中使用它。
BEGIN
INSERT INTO some_tbl (refnr,col1,col2,col3)
SELECT get_refnr,col1,col2,col3 from yoursourcetable;
--Your working select statement
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Error insert record ' || substr(SQLERRM,1, 250));
ROLLBACK;
END;
如果只想一次使用函数的输出作为常量,则可能需要一个变量来存储它,并且可以在上面的选择查询中使用它来代替函数调用。
答案 1 :(得分:1)
insert ... values
的语法是
insert into sometable (col1, col2, col3)
values (value1, value2, value3);
您的代码缺少两组括号。
有一个PL/SQL-only variant,其中的values
子句被PL / SQL记录代替了:
insert into sometable (col1, col2, col3)
values plsqlrecord;
这在值表达式中没有括号,但是它必须是PL / SQL记录,通常是sometable%rowtype
,而v_refnr
不是,因此是错误消息。
此外,Cursor FOR loop结构隐式生成自己的记录,在这种情况下,循环中的r_book
,而顶部使用的其他r_book
则不使用。因此,固定版本如下所示:
declare
v_refnr number;
cursor c_book is
select col1, col2, col3 from book;
begin
v_refnr := get_refnr;
for r_book in c_book loop
insert into some_tbl (col1, col2, col3)
values (v_refnr, col2, col3);
end loop;
end;
尽管我希望通过移动查询来消除游标声明:
declare
v_refnr number;
begin
v_refnr := get_refnr;
for r_book in (
select col1, col2, col3 from book
)
loop
insert into some_tbl (col1, col2, col3)
values (v_refnr, col2, col3);
end loop;
end;
我还通过删除when others
异常处理程序来改进了错误处理,该异常处理程序没有做任何有用的事情。未处理异常的默认处理是打印带有行号的错误堆栈,并将事务回滚到块的开头,并且尝试自己编写该代码将永远不会像以前那样好,因为会丢失原始的行号和块看起来实际上是成功完成的,更不用说将错误消息截断为250个字符没有任何好处。
这只会留下三个可能的问题:
您只会在顶部生成一次电话号码,而不会在插入的每一行生成一次电话号码。也许这是有目的的,但如果不是,则应在循环内移动函数调用。
如果所有get_refnr()
都产生一个序列号,那么Oracle已经提供了一种用于执行此操作的方法,称为sequence,或者更佳的是identity column。
如果循环的唯一目的是从select
语句中插入行,正如Kaushik Nayak指出的那样,您可以使用insert ... select
语法在普通SQL中完成此操作,而无需执行任何循环或变量等,它会更简单,更快。