英文:
Function call as a parameter inside insert values statement
问题
我正在尝试在一个forall
循环中插入数据。对于这种情况,我不能使用临时变量并在函数之前设置函数的结果。
该函数只是将一个数字映射到一个字符串:
create or replace function GetInvoiceStatus(status number)
return nvarchar2
as
begin
case status
when 0 then return 'New';
when 200 then return 'Sent';
when 300 then return 'Accepted';
end case;
return '';
end;
当我像这样调用这个函数时:
select GetInvoiceStatus(200) from dual;
我得到了适当的结果。
然而,当我尝试插入数据时,我遇到了错误。forall
插入如下:
forall i in 1.. INVOICE_DATA.COUNT
insert into "InvoiceAudit"
("PropertyName", "OldValue", "NewValue")
VALUES ('Status', (GetInvoiceStatus(invoice_data(i).status)), (GetInvoiceStatus((select "Status" from "Invoice" where "InvoiceId" = invoice_data(i).invoiceId))));
然而,我得到了以下错误:
[2023-06-01 15:02:57] [65000][6592] [2023-06-01 15:02:57] ORA-06592:
CASE not found while executing CASE statement [2023-06-01 15:02:57]
ORA-06512: at "PUBLIC.GETINVOICESTATUS", line 9 [2023-06-01 15:02:57]
ORA-06512: at "PUBLIC.INVOICESSP", line 63 [2023-06-01 15:02:57]
Position: 5
我已经仔细检查过,invoice_data(i).Status 和另一个 select 值的结果都是有效的参数(并且已经涵盖了它们的情况),在存储过程外部调用时返回适当的字符串。
语法是否有问题?如果可能的话,我想继续使用 forall
,因为它比常规的 for
循环快得多。
英文:
I'm trying to insert the data inside a forall
loop. For this case, I cannot use a temporary variable and set result of the function beforehand.
The function just maps a number to a string:
create or replace function GetInvoiceStatus(status number)
return nvarchar2
as
begin
case status
when 0 then return 'New';
when 200 then return 'Sent';
when 300 then return 'Accepted';
end case;
return '';
end;
when I call this function like:
select GetInvoiceStatus(200) from dual;
I get the appropriate result.
However, when I try to insert the data I get errors.
The forall
insert:
forall i in 1.. INVOICE_DATA.COUNT
insert into "InvoiceAudit"
("PropertyName", "OldValue", "NewValue" (
VALUES ('Status', (GetInvoiceStatus(invoice_data(i).status)),
((GetInvoiceStatus((select "Status" from "Invoice" where "InvoiceId" = invoice_data(i).invoiceId)))));
However, I get the following error:
> [2023-06-01 15:02:57] [65000][6592] [2023-06-01 15:02:57] ORA-06592:
> CASE not found while executing CASE statement [2023-06-01 15:02:57]
> ORA-06512: at "PUBLIC.GETINVOICESTATUS", line 9 [2023-06-01 15:02:57]
> ORA-06512: at "PUBLIC.INVOICESSP", line 63 [2023-06-01 15:02:57]
> Position: 5
I have double checked, and the results from invoice_data(i).Status and the other select value are both valid parameters (and have their cases covered) and return appropriate string when called outside the stored procedure.
Is the syntax somewhere wrong?
I would like to remain using forall
if at all possible because it is much faster than a regular for
loop.
答案1
得分: 4
这个错误意味着参数值(status)不是案例表达式中的一个情况(这些情况是0、200、300)。
如果你执行这段代码 select GetInvoiceStatus(555) as dd from dual
,你将会得到相同的错误。所以,像这样添加一个 ELSE
子句:
create or replace function GetInvoiceStatus(status number)
return nvarchar2
as
begin
case status
when 0 then return 'New';
when 200 then return 'Sent';
when 300 then return 'Accepted';
else return '';
end case;
end;
英文:
This error means that the parameter value (status) is not one of the cases in the case expression (which are 0, 200, 300).
If you executed this code select GetInvoiceStatus(555) as dd from dual
you will get the same error. So, add ELSE
clause like this:
create or replace function GetInvoiceStatus(status number)
return nvarchar2
as
begin
case status
when 0 then return 'New';
when 200 then return 'Sent';
when 300 then return 'Accepted';
else return '';
end case;
end;
答案2
得分: 2
CASE作为PL/SQL表达式(而不是通常在SQL中使用的返回结果的函数)必须执行某些操作。如果没有任何条件匹配,它将无事可做:
DECLARE
var_test integer := 1;
BEGIN
CASE var_test
WHEN 2 THEN null;
END CASE;
END;
会引发ORA-06592错误。要修复这个问题,添加一个ELSE
来捕获不满足其他WHEN
条件的情况:
DECLARE
var_test integer := 1;
BEGIN
CASE var_test
WHEN 2 THEN null;
ELSE null;
END CASE;
END;
这样可以正常工作。再次注意,这个要求仅适用于将CASE..END CASE
作为PL/SQL表达式使用的情况。大多数情况下,我们看到的CASE
是一个函数,不需要像这样添加ELSE
(如果没有匹配的WHEN子句,它将返回NULL
)。但是PL/SQL表达式是一个不同的东西。
我还要补充一点,您不应该使用用户定义的函数来实现这个。只需在您的SQL中直接使用SQL函数CASE
或甚至DECODE
来进行翻译即可。
英文:
CASE used as a PL/SQL expression (rather than a function that returns a result, as it is commonly used in SQL) has to do something. If none of your conditions match, it has nothing to do:
DECLARE
var_test integer := 1;
BEGIN
CASE var_test
WHEN 2 THEN null;
END CASE;
END;
Throws the ORA-06592 error. To fix, add an ELSE
to catch anything that doesn't satisfy your other WHEN
conditions.
DECLARE
var_test integer := 1;
BEGIN
CASE var_test
WHEN 2 THEN null;
ELSE null;
END CASE;
END;
Works fine. Note again that this requirement only exists for CASE..END CASE
used as a PL/SQL expression. Most of the time we see CASE
it's a function and doesn't have to have an ELSE
like this (it will return NULL
if no WHEN clauses are matched). But the PL/SQL expression is a different animal.
I would also add that you shouldn't be using a user-defined function for this. Simply use the SQL function CASE
or even DECODE
inside your SQL directly to do the translation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论