需要 ORA-01422 的解决方案:精确提取返回的行数超过请求的行数
Posted
技术标签:
【中文标题】需要 ORA-01422 的解决方案:精确提取返回的行数超过请求的行数【英文标题】:Need solution for ORA-01422: exact fetch returns more than requested number of rows 【发布时间】:2020-03-18 12:16:31 【问题描述】:我被要求在 Oracle 中为以下查询创建一个存储过程,该过程将在 where 子句中将输入参数作为 @FID
给我结果。
它由 4 列组成,每个不同输入的结果通常是 100+ 行。 初始查询如下-
SELECT
TJV.FID, TD.F_CLASS_NAME,
CASE
WHEN TJV.job_operation_id = 1 THEN 'INSERT'
WHEN TJV.JOB_OPERATION_ID = 2 THEN 'UPDATE'
WHEN TJV.job_operation_id = 3 THEN 'DELETE'
END AS JOB_OPERATION_TYPE,
TJV.OPERATION_DATE
FROM
TB_JOB_VERSION TJV,
TB_DICTIONARY TD, TB_UFID TU
WHERE
TJV.JOB_ID = @FID
AND TU.FID = TJV.FID
AND TU.F_CLASS_ID = TD.F_CLASS_ID;
然后我在下面做了一个这样的过程,但它抛出了下面的错误消息 -
ORA-01422:精确提取返回的行数多于请求的行数 ORA-06512:在 TCGM3D.JOB_EXPLORER,第 8 行 ORA-06512:在第 6 行
代码:
CREATE OR REPLACE PROCEDURE job_explorer (
j_fid IN INT
) AS
v_fid NUMBER;
v_f_class_name VARCHAR2(30);
v_job_operation_type VARCHAR(100);
v_operation_date DATE;
BEGIN
SELECT
tjv.fid,
td.f_class_name,
CASE
WHEN tjv.job_operation_id = 1 THEN
'INSERT'
WHEN tjv.job_operation_id = 2 THEN
'UPDATE'
WHEN tjv.job_operation_id = 3 THEN
'DELETE'
END AS job_operation_type,
tjv.operation_date
INTO
v_fid,
v_f_class_name,
v_job_operation_type,
v_operation_date
FROM
tcgm3d.tb_job_version tjv,
tcgm3d.tb_dictionary td,
tcgm3d.tb_ufid tu
WHERE
tjv.job_id = j_fid
AND tu.fid = tjv.fid
AND tu.f_class_id = td.f_class_id;
dbms_output.put_line('FID'
|| v_fid
|| 'F_CLASS_NAME'
|| v_f_class_name
|| 'JOB_OPERATION_TYPE'
|| v_job_operation_type
|| 'OPERATION_DATE'
|| v_operation_date);
END job_explorer;
我再次尝试使用循环修改查询,但结果不是表格,它只是在查询输出窗口中出现-
"FID85225493
F_CLASS_NAMESCE_EL_TRN_POLE_TBL
JOB_OPERATION_TYPEUPDATE
OPERATION_DATE04-JAN-17
FID251101047
F_CLASS_NAMESCE_EL_SEG_SECTION
JOB_OPERATION_TYPEINSERT
OPERATION_DATE04-JAN-17
FID251101038
F_CLASS_NAMEEL_CONNECTOR
JOB_OPERATION_TYPEINSERT
OPERATION_DATE04-JAN-17
FID251100923
F_CLASS_NAMEEL_PAD
JOB_OPERATION_TYPEINSERT
OPERATION_DATE04-JAN-17"
我对此的最终查询如下-
CREATE OR REPLACE PROCEDURE job_explorer (
j_fid IN INT
) AS
BEGIN
FOR rec IN (
SELECT
tjv.fid,
td.f_class_name,
CASE
WHEN tjv.job_operation_id = 1 THEN
'INSERT'
WHEN tjv.job_operation_id = 2 THEN
'UPDATE'
WHEN tjv.job_operation_id = 3 THEN
'DELETE'
END AS job_operation_type,
tjv.operation_date
FROM
tcgm3d.tb_job_version tjv,
tcgm3d.tb_dictionary td,
tcgm3d.tb_ufid tu
WHERE
tjv.job_id = j_fid
AND tu.fid = tjv.fid
AND tu.f_class_id = td.f_class_id
) LOOP
dbms_output.put_line('FID' || rec.fid);
dbms_output.put_line('F_CLASS_NAME' || rec.f_class_name);
dbms_output.put_line('JOB_OPERATION_TYPE' || rec.job_operation_type);
dbms_output.put_line('OPERATION_DATE' || rec.operation_date);
END LOOP;
END job_explorer;
如果有人可以帮助我以表格格式获取每一行的数据,我必须在 ado.net 的数据表中查询这些数据。
【问题讨论】:
只需将 dbms_output.put_line 更改为一次调用并连接所有字段。 另请参阅 Microsoft 文档,了解如何使用 Oracle 引用游标填充数据集。 docs.microsoft.com/en-us/dotnet/framework/data/adonet/… 光标(rec)中的数据是表格的,dbms_output 不是。每次调用 dbms_output.put_line 都会产生 1 行输出。您可以连接每个字段(在字段之间使用合适的分隔符)或将 dbms_output.put_line 更改为 dbms_output.put(然后使用合适的分隔符),然后添加 dbms_output.new_line。 @Belayer -- 我的主要问题是我需要使用这个存储过程来通过 ado dot net dataset/data table 获取数据,我想再次绑定到网格视图但是使用这个数据表只是空 Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 ANSI 中的 proper ANSIJOIN
语法-92 SQL 标准(25 多年前),不鼓励使用它
【参考方案1】:
这样你就可以得到表格形式的答案,用竖线作为分隔符:
CREATE OR REPLACE PROCEDURE job_explorer(j_fid IN INT)
AS
BEGIN
/* header */
dbms_output.put_line( rpad('FID',12)
||'|'||rpad('F_CLASS_NAME',30)
||'|'||rpad('JOB_OPERATION_TYPE',18)
||'|'||rpad('OPERATION_DATE',19)
);
--
/*data*/
FOR rec IN (SELECT tjv.fid,
td.f_class_name,
CASE
WHEN tjv.job_operation_id = 1 THEN
'INSERT'
WHEN tjv.job_operation_id = 2 THEN
'UPDATE'
WHEN tjv.job_operation_id = 3 THEN
'DELETE'
END AS job_operation_type,
tjv.operation_date
FROM tcgm3d.tb_job_version tjv,
tcgm3d.tb_dictionary td,
tcgm3d.tb_ufid tu
WHERE tjv.job_id = j_fid
AND tu.fid = tjv.fid
AND tu.f_class_id = td.f_class_id
) LOOP
--
dbms_output.put_line( lpad(rec.fid,12)
||'|'||rpad(rec.f_class_name,30)
||'|'||rpad(rec.job_operation_type,18)
||'|'||to_char(rec.operation_date,'dd-MON-yy')
);
END LOOP;
END job_explorer;
输出将是:
FID |F_CLASS_NAME |JOB_OPERATION_TYPE|OPERATION_DATE
85225493|SCE_EL_TRN_POLE_TBL |UPDATE |04-JAN-17
251101047|SCE_EL_SEG_SECTION |INSERT |04-JAN-17
251101038|EL_CONNECTOR |INSERT |04-JAN-17
251100923|EL_PAD |INSERT |04-JAN-17
【讨论】:
我的主要问题是我需要使用这个存储过程来通过 ado dot net dataset/data table 获取数据,我想再次绑定到网格视图,但是数据表只是 null 你可以使用一个输出参数来获取这个输出以上是关于需要 ORA-01422 的解决方案:精确提取返回的行数超过请求的行数的主要内容,如果未能解决你的问题,请参考以下文章
PL/SQL ORA-01422:精确提取返回的行数超过了请求的行数
获取 ORA-01422 的原因:精确提取返回的行数超过了请求的行数