use*_*er1 6 oracle plsql stored-procedures oracle10g oracle11g
下面的代码可能会返回多行.会sql%rowcount返回获取的行数吗?
select * from emp where empname = 'Justin' and dept='IT'
if sql%rowcount>0
...
Run Code Online (Sandbox Code Playgroud)
这是我的样本过程; 我用的sql%rowcount是正确的吗?
CREATE PROCEDURE Procn(in_Hid IN VARCHAR2,outInststatus OUT VARCHAR2,outSockid IN NUMBER,outport OUT VARCHAR2,outIP OUT VARCHAR2,outretvalue OUT NUMBER)
AS
BEGIN
select INST_STATUS into outInststatus from TINST_child where INST_ID = in_Hid and INST_STATUS = 'Y';
if outInststatus = 'Y' then
select PORT_NUMBER,STATIC_IP into outport,outIP from TINST where INST_ID = in_Hid and IP_PORT_STATUS = 'Y';
if sql%rowcount >= 1 then
select SOCK_ID into outSockid from TINST where PORT_NUMBER = outport AND STATIC_IP = outIP;
outretvalue := 0;
else
outretvalue := -12;
end if;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -13;
end if;
END;
Run Code Online (Sandbox Code Playgroud)
是的,你可以使用SQL%ROWCOUNT.它在PL/SQL中有效.
但是,在PL/SQL中,查询的结果需要转移到某个PL/SQL表中.PL/SQL永远不会将结果发送到输出(终端,窗口等).所以SELECT * FROM不行.
您的代码可能如下所示:
DECLARE
TYPE emp_t ...;
emp_tab emp_t;
BEGIN
SELECT *
BULK COLLECT INTO emp_tab
FROM emp
WHERE empname = 'Justin' AND dept='IT';
IF sql%rowcount > 0 THEN
.. do something ...
END IF;
END;
/
Run Code Online (Sandbox Code Playgroud)
更新:
更新的问题表明您正在寻找其他东西.
选项1:使用例外
如果有0行或多于1行,则这些情况将单独处理(作为错误):
BEGIN
select PORT_NUMBER,STATIC_IP into outport, outIP
from TINST
where INST_ID = in_Hid AND IP_PORT_STATUS = 'Y';
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -12;
RETURN;
WHEN TOO_MANY_ROWS THEN
outretvalue := -13;
RETURN;
END;
Run Code Online (Sandbox Code Playgroud)
选项2:使用聚合
使用聚合,查询将始终返回一行.如果现在源行与WHERE子句匹配,则两个结果值都将为NULL.如果WHERE子句匹配多行,则将采用最大值.
请注意,此查询可能会返回端口号和最初不在同一行的IP地址.
select MAX(PORT_NUMBER), MAX(STATIC_IP) into outport, outIP
from TINST
where INST_ID = in_Hid AND IP_PORT_STATUS = 'Y';
IF outport IS NULL OR outIP IS NULL THEN
outretvalue := -12;
RETURN;
END IF;
Run Code Online (Sandbox Code Playgroud)
选项3:使用ROWNUM
此查询最多返回一行.如果没有与WHERE子句匹配的行,则抛出异常并需要处理:
BEGIN
select PORT_NUMBER, STATIC_IP into outport, outIP
from TINST
where INST_ID = in_Hid AND IP_PORT_STATUS = 'Y'
AND ROWNUM = 1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -12;
RETURN;
END;
Run Code Online (Sandbox Code Playgroud)
根据您的评论
如果第二个“选择”查询返回多行,我想获取第一行并对其进行处理
...这应该有效,但可能不完全符合您的预期,因为您还没有定义“第一个”的含义。
CREATE PROCEDURE Procn(in_Hid IN VARCHAR2, outInststatus OUT VARCHAR2,
outSockid IN NUMBER, outport OUT VARCHAR2, outIP OUT VARCHAR2,
outretvalue OUT NUMBER)
AS
BEGIN
select INST_STATUS into outInststatus
from TINST_child
where INST_ID = in_Hid and INST_STATUS = 'Y';
-- no need to check if outInstatus is Y, that's all it can be here
-- restricting with `rownum` means you'll get at most one row, so you will
-- not get too_many_rows. But it will be an arbitrary row - you have no
-- criteria to determine which of the multiple rows you want. And you can
-- still get no_data_found which will go to the same exception and set -12
select PORT_NUMBER, STATIC_IP into outport, outIP
from TINST
where INST_ID = in_Hid and IP_PORT_STATUS = 'Y'
and rownum < 2;
-- no need to check sql%rowcount; it can only be 1 here
-- not clear if this can return multiple rows too, and what should happen
-- if it can; could use rownum restriction but with the same caveats
select SOCK_ID into outSockid
from TINST
where PORT_NUMBER = outport AND STATIC_IP = outIP;
outretvalue := 0;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -12;
END;
Run Code Online (Sandbox Code Playgroud)
该exception处理程序适用于整个块。如果任何语句select找不到行,则该no_data_found异常将由该块处理并设置outretvalue为-12。
outretvalue如果您想要每个都不同,select那么您可以将它们包装在子块中,每个子块都有自己的异常处理部分:
CREATE PROCEDURE Procn(in_Hid IN VARCHAR2, outInststatus OUT VARCHAR2,
outSockid IN NUMBER, outport OUT VARCHAR2, outIP OUT VARCHAR2,
outretvalue OUT NUMBER)
AS
BEGIN
BEGIN
select INST_STATUS into outInststatus
from TINST_child
where INST_ID = in_Hid and INST_STATUS = 'Y';
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -12;
END;
BEGIN
select PORT_NUMBER, STATIC_IP into outport, outIP
from TINST
where INST_ID = in_Hid and IP_PORT_STATUS = 'Y'
and rownum < 2;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -13;
END;
BEGIN
select SOCK_ID into outSockid
from TINST
where PORT_NUMBER = outport AND STATIC_IP = outIP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
outretvalue := -14;
END;
outretvalue := 0;
END;
Run Code Online (Sandbox Code Playgroud)
仅当调用者需要知道哪个失败时才需要这样做select,并且如果您从未真正期望其中任何一个失败,那么更常见的情况可能是根本不捕获异常并让调用者查看原始数据no_data_found并决定要做什么。不过,取决于异常情况对您和您的应用程序意味着什么。
| 归档时间: |
|
| 查看次数: |
49410 次 |
| 最近记录: |