为啥我在更新语句后使用 RETURNING 子句时收到“NO DATA FOUND”异常?
Posted
技术标签:
【中文标题】为啥我在更新语句后使用 RETURNING 子句时收到“NO DATA FOUND”异常?【英文标题】:Why I receive "NO DATA FOUND" exception when I use RETURNING clause after update statement?为什么我在更新语句后使用 RETURNING 子句时收到“NO DATA FOUND”异常? 【发布时间】:2017-02-02 15:53:57 【问题描述】:我正在编写一个简单的 LOOP FOR 代码,以使用关联数组中填充的信息更新表中的列。当我只使用 UPDATE 语句时,一切似乎都是正确的,但是当我添加一个 RETURNING 子句时,我收到“NO DATA FOUND”错误。谢谢!
DECLARE
TYPE emps_info IS TABLE OF employees23%ROWTYPE
INDEX BY PLS_INTEGER;
t_emps_current_info emps_info;
t_emps_new_info emps_info;
BEGIN
SELECT *
BULK COLLECT INTO t_emps_current_info
FROM employees;
FOR emps_index IN t_emps_current_info.FIRST .. t_emps_current_info.LAST
LOOP
IF
NVL(t_emps_current_info(emps_index).commission_pct, 0) = 0 THEN
UPDATE employees23
SET commission_pct = 0.3
WHERE employee_id = t_emps_current_info(emps_index).employee_id;
ELSIF
t_emps_current_info(emps_index).commission_pct BETWEEN 0.1 AND 0.3 THEN
UPDATE employees23
SET commission_pct = 0.5
WHERE employee_id = t_emps_current_info(emps_index).employee_id;
END IF;
END LOOP;
END;
现在当我添加 RETURNING 子句时,我收到以下错误:
DECLARE
TYPE emps_info IS TABLE OF employees23%ROWTYPE
INDEX BY PLS_INTEGER;
t_emps_current_info emps_info;
t_emps_new_info emps_info;
BEGIN
SELECT *
BULK COLLECT INTO t_emps_current_info
FROM employees;
FOR emps_index IN t_emps_current_info.FIRST .. t_emps_current_info.LAST
LOOP
IF
NVL(t_emps_current_info(emps_index).commission_pct, 0) = 0 THEN
UPDATE employees23
SET commission_pct = 0.3
WHERE employee_id = t_emps_current_info(emps_index).employee_id
RETURNING commission_pct
INTO t_emps_new_info(emps_index).commission_pct;
ELSIF
t_emps_current_info(emps_index).commission_pct BETWEEN 0.1 AND 0.3 THEN
UPDATE employees23
SET commission_pct = 0.5
WHERE employee_id = t_emps_current_info(emps_index).employee_id
RETURNING commission_pct
INTO t_emps_new_info(emps_index).commission_pct;
END IF;
DBMS_OUTPUT.PUT_LINE('EMPLOYEE_ID: ' ||
t_emps_current_info(emps_index).employee_id ||
' OLD COMMISSION: ' ||
NVL(t_emps_current_info(emps_index).commission_pct, 0)
|| ' NEW COMMISSION: ' ||
t_emps_new_info(emps_index).commission_pct);
END LOOP;
END;
通知错误 - ORA-01403: 未找到数据 ORA-06512: 在第 22 行 01403. 00000 - “未找到数据” *原因:没有从对象中找到数据。 *操作:对象中没有数据,可能是由于提取结束。
【问题讨论】:
【参考方案1】:代码中的这部分
DBMS_OUTPUT.PUT_LINE('EMPLOYEE_ID: ' ||
t_emps_current_info(emps_index).employee_id ||
' OLD COMMISSION: ' ||
NVL(t_emps_current_info(emps_index).commission_pct, 0)
|| ' NEW COMMISSION: ' ||
t_emps_new_info(emps_index).commission_pct);
打印原始数组和返回数组。
在更新期间的某个时间点,您的更新语句可能不会更新任何行,在这种情况下,您的原始数组将在该索引处具有值,但您返回的数组不会
所以检查索引是否存在以避免这个错误
case when t_emps_new_info.exists(emps_index) then
dbms_output.put_line('print something') ;
else dbms_output.put_line('print something else') ;
end case;
【讨论】:
【参考方案2】:您得到 NO_DATA_FOUND 是因为您在代码中没有任何地方初始化(创建)t_emps_new_info(emps_index)
记录 - 每当您的代码尝试分配 t_emps_new_info(emps_index).commission_pct
时,它都会失败。
【讨论】:
【参考方案3】:我不确定为什么必须这样做,但我会将每个 UPDATE 语句的返回值更改为一个简单的局部变量。然后我将表记录字段设置为简单变量。
可能不相关,但我注意到您的 ELSIF 测试没有像您的 IF 测试那样对现有的 t_emps_current_info(emps_index).commission_pct 执行 NVL()。
如果是我,我会记录 IF-ELSEIF 两侧的更新,以查看一个更新是否有效而另一个更新失败。也许它只是在 ELSIF 上失败了,因为缺少 NVL()?
【讨论】:
以上是关于为啥我在更新语句后使用 RETURNING 子句时收到“NO DATA FOUND”异常?的主要内容,如果未能解决你的问题,请参考以下文章
防止 NHibernate 将 Returning 子句添加到生成的插入语句中
Oracle 是不是支持 SQL 语句中的 RETURNING?
在 PL/SQL Developer 中使用了没有 Where 子句的更新语句