使用Select Into MULTIPLE变量进行NO_DATA_FOUND异常处理



我已经为这个问题寻找了一段时间的解决方案,我找到的所有NO_DATA_FOUND处理教程都只展示了如何在一个变量中只包含一列的情况下执行SelectInto。

首先,这是我的代码:

BEGIN 
OPEN c_no_source; 
LOOP 
DECLARE 
l_price_code  VARCHAR2(20) := ''; 
l_price_level VARCHAR(10) := ''; 
l_code_date   DATE := p_effective_date; 
BEGIN 
FETCH c_no_source INTO c_no_source_row;
exit WHEN c_no_source%NOTFOUND;
BEGIN 
WITH codeList AS /* liste des dates ayant une donnée avant la date effective incluse. */
(
SELECT distinct
NVL(effective_date,p_effective_date) as effective_date,
NVL(user_group2,'') as price_code, 
NVL(user_group3,'') as price_level
FROM  DGA_Service.Hjvsecmaster_Hist
WHERE   effective_date <= p_effective_date
AND user_group2 IS NOT NULL
AND security_alias = c_no_source_row.security_alias
ORDER BY 1 DESC
)
SELECT price_code, price_level, effective_date 
INTO   l_price_code, l_price_level, l_code_date 
FROM   codelist 
WHERE  ROWNUM = 1; 
EXCEPTION WHEN no_data_found THEN NULL;
...
[UPDATE statement using the variables] 
...
END; 
END; 
END LOOP; 
CLOSE c_no_source; 
END; 

我要做的是将codeList临时结果集的前1个结果分成三个独立的变量。然而,CCD_ 2中的三个列中的一个通常是CCD_。我的3个变量都不会被设置。我试图处理这个异常,但我无法让代码将确实有值的列插入到它们各自的变量中。如果其中一列为NULL,则不会将任何列插入其变量中。

我希望SelectInto语句设置它可以设置的变量。

我试着用这样的东西分别处理它们:

EXCEPTION WHEN NO_DATA_FOUND THEN
BEGIN
IF price_code IS NOT NULL THEN l_price_code := price_code; END IF;
IF price_level IS NOT NULL THEN l_price_level := price_level; END IF;
IF effective_date IS NOT NULL THEN l_code_date := effective_date; END IF;
END;

但我收到以下错误消息:

ORA-06550: line 294, column 18:
PLS-00201: identifier 'PRICE_CODE' must be declared
ORA-06550: line 294, column 15:
PL/SQL: Statement ignored
ORA-06550: line 295, column 18:
PLS-00201: identifier 'PRICE_LEVEL' must be declared
ORA-06550: line 295, column 15:
PL/SQL: Statement ignored
ORA-06550: line 296, column 18:
PLS-00201: identifier 'EFFECTIVE_DATE' must be declared
ORA-06550: line 296, column 15:
PL/SQL: Statement ignored

所以我没什么想法了。我试着指定临时表名称,但没有成功,比如:

IF codeList.price_code IS NOT NULL

我希望在这个问题上能得到任何帮助。这段代码运行的包已经很重了,我不希望每个列都有一个单独的With ... As () Select Into子句。

好吧,我想我明白了;您的大部分问题是由错误地嵌套PL/SQL块引起的。

update语句包含在EXCEPTION块中,这意味着只有在抛出异常时才会执行它。其次,您直接在下面引用

EXCEPTION WHEN NO_DATA_FOUND THEN
BEGIN
IF price_code IS NOT NULL THEN l_price_code := price_code; END IF;
IF price_level IS NOT NULL THEN l_price_level := price_level; END IF;
IF effective_date IS NOT NULL THEN l_code_date := effective_date; END IF;
END;

这就是编译错误的原因。

最后,如果select into中只有一行,则将设置每个变量,因此无需尝试处理此问题。

BEGIN 
OPEN c_no_source; 
LOOP 
DECLARE 
l_price_code  VARCHAR2(20); 
l_price_level VARCHAR(10); 
l_code_date   DATE := p_effective_date; 
BEGIN 
FETCH c_no_source INTO c_no_source_row;
exit WHEN c_no_source%NOTFOUND;
BEGIN 
WITH codelist AS (
SELECT DISTINCT effective_date
, user_group2 AS price_code
, user_group3 AS price_level 
FROM hjvsecmaster_hist 
WHERE effective_date <= p_effective_date 
AND user_group2 IS NOT NULL 
AND security_alias = c_no_source_row.security_alias 
ORDER BY 1 DESC
) 
SELECT price_code, price_level, effective_date 
INTO   l_price_code, l_price_level, l_code_date 
FROM   codelist 
WHERE  ROWNUM = 1; 
EXCEPTION WHEN no_data_found THEN
-- All variables are their initial setting
null;
END; 
...
[UPDATE statement using the variables] 
...
END; 
END LOOP; 
CLOSE c_no_source; 
END; 

这通常是一种效率很低的方法。如果你能把所有东西都放在一个UPDATE或MERGE中,那么我会这么做。你似乎没有任何额外的逻辑,所以这应该是可能的。

然而,三者中的一个通常为NULL,并触发NO_DATA_FOUND错误,我的3个变量都不会设置

NO_DATA_FOUND在查询未返回任何时引发。它与列值无关。它们都可能为空,并且声明将成功。

EXCEPTION WHEN NO_DATA_FOUND THEN
BEGIN
IF price_code IS NOT NULL THEN l_price_code := price_code; END IF;
IF price_level IS NOT NULL THEN l_price_level := price_level; END IF;
IF effective_date IS NOT NULL THEN l_code_date := effective_date; END IF;
END;

您的变量以"l"为前缀,并且您在比较中使用了列名eg.pricecode,因此出现了错误更重要的是,NO_DATA_FOUND意味着所有变量值都为null,因此此异常块不会执行任何操作

你可能只需要这个。

如果你不想为给定的id插入null值(如果全部为null)

BEGIN
insert into target_table (id, col1, col2, col3)
select id, col1, col2, col3
from (target_table)
where not (col1 is null and col2 is null and col3 is null);
commit;
end;
/

如果没有给定id的数据,则不会插入任何内容。如果其中至少有一个值不为null,则插入这些值。

最新更新