以下のコードは、複数の行を返す場合があります。 sql%rowcount
はフェッチされた行数を返しますか?
select * from emp where empname = 'Justin' and dept='IT'
if sql%rowcount>0
...
これは私のサンプルプロシージャです。 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;
あなたのコメントに基づいて
2番目の「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
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;
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;
呼び出し元がどのselect
が失敗したかを知る必要がある場合にのみこれを行う必要があり、それらのいずれかが失敗することを本当に期待しない場合は、例外をまったくキャッチせず、呼び出し元に生のno_data_found
そして何をすべきかを決定します。ただし、例外条件がユーザーとアプリケーションにとって何を意味するかによって異なります。
はい、SQL%ROWCOUNT
を使用できます。 PL/SQLで有効です。
ただし、PL/SQLでは、クエリの結果はどこかに移動する必要があります。 PL/SQL表に。 PL/SQLは、結果をoutput(ターミナル、ウィンドウなど)に送信することはありません。したがって、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;
/
更新:
更新された質問は、あなたが何か他のものを探していることを示唆しています。
オプション1:例外を使用
0行または複数行がある場合、これらのケースは個別に(エラーとして)処理されます。
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;
オプション2:集計を使用
集計を使用すると、クエリは常に正確に1行を返します。ソース行が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;
オプション3:ROWNUMを使用
このクエリは最大で1行を返します。 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;