Oracle 引用游标异常
我有几个关于参考光标的问题。下面是一个ref_游标,它根据传入的内容向Unix调用脚本返回一行,尽管select看起来有点不整洁,但仍能正常工作 我的第一个问题是,在select中,我连接到一个查找表以检索单个查找值“trigram”,并且在测试中发现,由于不存在任何值,该连接偶尔会失败。我试图在没有找到任何数据的情况下捕捉到这一点,当其他人出现异常时,但这似乎不起作用 理想情况下,如果连接失败,我仍然希望将值返回到ref_游标,但在Trigram字段中添加类似“No Trigram”的内容-主要是我希望捕获异常 我的第二个问题是关于ref_游标的更一般的问题-虽然最初我在其自己的过程中创建了它,但它可能会被主处理过程调用多次,其中一个条件需要单独的select,但该过程在调用时只会返回一个ref_cur,过程引用是否可以与2个查询相关联Oracle 引用游标异常,oracle,plsql,oracle11g,Oracle,Plsql,Oracle11g,我有几个关于参考光标的问题。下面是一个ref_游标,它根据传入的内容向Unix调用脚本返回一行,尽管select看起来有点不整洁,但仍能正常工作 我的第一个问题是,在select中,我连接到一个查找表以检索单个查找值“trigram”,并且在测试中发现,由于不存在任何值,该连接偶尔会失败。我试图在没有找到任何数据的情况下捕捉到这一点,当其他人出现异常时,但这似乎不起作用 理想情况下,如果连接失败,我仍然希望将值返回到ref_游标,但在Trigram字段中添加类似“No Trigram”的内容-主
CREATE OR REPLACE PROCEDURE OPC_OP.SiteZone_status
(in_site_id IN AW_ACTIVE_ALARMS.site_id%TYPE
,in_zone_id IN AW_ACTIVE_ALARMS.zone_id%TYPE
,in_mod IN AW_ACTIVE_ALARMS.module%TYPE
,p_ResultSet OUT TYPES.cursorType
)
AS
BEGIN
OPEN p_ResultSet FOR
SELECT a.site_id,'~',a.zone_id,'~',b.trigram,'~',a.module,'~',a.message_txt,'~',a.time_stamp
FROM AW_ACTIVE_ALARMS a, AW_TRIGRAM_LOCATION b
WHERE a.site_id = b.site_id
AND a.zone_id = b.zone_id
AND a.site_id = in_site_id
AND a.zone_id = in_zone_id
AND a.module LIKE substr(in_mod,1,3)||'%'
AND weight = (select max(weight) from AW_ACTIVE_ALARMS c
WHERE c.site_id = in_site_id
AND c.zone_id = in_zone_id
AND c.module LIKE substr(in_mod,1,3)||'%');
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('No Data Found');
END SiteZone_status;
我已经修改了我的代码,以采用提供的答案,现在它在我的包中作为一个独立过程正常工作,当通过UNIX脚本调用时,使用:
v_进程_报警=$(sqlplus-s用户/通过)<
设置colsep','
设置行大小为500
关闭第0页反馈;
打开服务器输出;
变量结果集REFCURSOR
EXEC alarm_pkg.rtn_active_alarm($site,$zone,$module,$resultSet);
打印:结果集
EOF
)
但是,返回ref游标的过程将从主处理过程调用,因为我只想在满足某些条件时返回值。我在我的主过程中添加了一个out refcurosr,并设置了一个匹配的变量,然后从这里调用我的ref cursor过程,但编译失败
带有消息“调用中参数的数目或类型错误”
我的问题是,从过程中调用没有refcursor的过程,然后将这些值返回到调用脚本的正确方法是什么。您可以使用左外部联接到查找表,如果使用ANSI联接语法而不是Oracle的旧语法,这一点会更清楚。如果
AW\u TRIGRAM\u位置中没有记录
,则b.TRIGRAM
将为空,然后您可以使用NVL
分配一个虚拟值:
OPEN p_ResultSet FOR
SELECT a.site_id,'~',a.zone_id,'~',NVL(b.trigram, 'No Trigram'),'~',
a.module,'~',a.message_txt,'~',a.time_stamp
FROM AW_ACTIVE_ALARMS a
LEFT JOIN AW_TRIGRAM_LOCATION b
ON b.site_id = a.site_id
AND b.zone_id = a.zone_id
WHERE a.zone_id = in_zone_id
AND a.module LIKE substr(in_mod,1,3)||'%'
AND weight = (select max(weight) from AW_ACTIVE_ALARMS c
WHERE c.site_id = in_site_id
AND c.zone_id = in_zone_id
AND c.module LIKE substr(in_mod,1,3)||'%');
只有当您从游标中提取数据时(取决于实际使用的数据),打开游标时才会得到
NO\u DATA\u FOUND
。当其他人时捕获是个坏主意-当没有找到数据时捕获,尽管在这里没有帮助。使用dbms\u output
报告错误依赖于客户端启用其显示,这是您通常无法假设的。您可以使用左外部联接到查找表,如果使用ANSI联接语法而不是Oracle的旧语法,这一点会更清楚。如果AW\u TRIGRAM\u位置中没有记录
,则b.TRIGRAM
将为空,然后您可以使用NVL
分配一个虚拟值:
OPEN p_ResultSet FOR
SELECT a.site_id,'~',a.zone_id,'~',NVL(b.trigram, 'No Trigram'),'~',
a.module,'~',a.message_txt,'~',a.time_stamp
FROM AW_ACTIVE_ALARMS a
LEFT JOIN AW_TRIGRAM_LOCATION b
ON b.site_id = a.site_id
AND b.zone_id = a.zone_id
WHERE a.zone_id = in_zone_id
AND a.module LIKE substr(in_mod,1,3)||'%'
AND weight = (select max(weight) from AW_ACTIVE_ALARMS c
WHERE c.site_id = in_site_id
AND c.zone_id = in_zone_id
AND c.module LIKE substr(in_mod,1,3)||'%');
只有当您从游标中提取数据时(取决于实际使用的数据),打开游标时才会得到NO\u DATA\u FOUND
。当其他人
时捕获是个坏主意-当没有找到数据时捕获,尽管在这里没有帮助。使用dbms\u output
报告错误依赖于客户端启用其显示,这通常是无法假设的。Oracle不知道查询是否会返回行,直到您从光标获取。查询返回0行不是错误。因此,打开光标时将永远不会出现no\u data\u found
异常。只有当您在局部变量中执行类似于选择的操作时,才会得到该结果,在这种情况下,返回0或1行以上的查询是错误的
听起来您想对AW\u TRIGRAM\u位置执行外部联接
,而不是当前的内部联接。这将从其他表返回数据,即使aw\u trigram\u位置中没有匹配的行
。这看起来像这样(我不知道为什么其他每一列都是硬编码的平铺字符,这似乎异常奇怪)
我不太确定我是否理解你的最后一个问题。您当然可以在过程中加入逻辑,根据输入参数运行不同的查询。差不多
IF( <<some condition>> )
THEN
OPEN p_ResultSet FOR <<query 1>>
ELSE
OPEN p_ResultSet FOR <<query 2>>
END IF;
IF()
然后
打开的p_结果集
其他的
打开的p_结果集
如果结束;
这样做是否有意义,而不是添加额外的谓词或创建单独的过程,这是您必须回答的问题。Oracle不知道在您从游标获取之前,查询是否会返回行。查询返回0行不是错误。因此,打开光标时将永远不会出现no\u data\u found
异常。只有当您在局部变量中执行类似于选择的操作时,才会得到该结果,在这种情况下,返回0或1行以上的查询是错误的
听起来您想对AW\u TRIGRAM\u位置执行外部联接
,而不是当前的内部联接。这将从其他表返回数据,即使aw\u trigram\u位置中没有匹配的行
。这看起来像这样(我不知道为什么其他每一列都是硬编码的平铺字符,这似乎异常奇怪)
我不太确定我是否理解你的最后一个问题。您当然可以在过程中加入逻辑,根据输入参数运行不同的查询。差不多
IF( <<some condition>> )
THEN
OPEN p_ResultSet FOR <<query 1>>
ELSE
OPEN p_ResultSet FOR <<query 2>>
END IF;
IF()
然后
打开的p_结果集
其他的
打开的p_结果集
如果结束;
这样做是否有意义,而不是添加额外的谓词或创建单独的过程,这是您必须回答的问题