我已经为这个问题寻找了一段时间的解决方案,我找到的所有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,则插入这些值。