CREATE OR REPLACE FUNCTION get_status_by_member_id
(p_member_id NUMBER)
RETURN CHAR
AS
v_status CHAR(1);
BEGIN
select status
into v_status
from members
where member_id = p_member_id;
if v_status is null then
return v_status || 'N';
else
return v_status;
end if;
END get_status_by_member_id;
2 に答える
あなたの問題は、時々迷惑な Oracle の癖によって引き起こされます。つまり、PL/SQL 関数が SQL で呼び出され、エラーnull
が返された場合は、他のものではなく返されます。
非常に単純なテーブルを作成すると...
create table a ( b number, c varchar2(1) );
insert into a values (1,'Y');
...そして2つの機能。例外処理のないもの
create or replace function tmp_ben_fn (PId number) return char is
l_status varchar2(1);
begin
select c
into l_status
from a
where b = PId;
return coalesce(l_status, 'N');
end;
/
もう 1 つは例外処理付きです。
create or replace function tmp_ben_fn2 (PId number) return char is
l_status varchar2(1);
begin
select c
into l_status
from a
where b = PId;
return coalesce(l_status, 'N');
exception when no_data_found then
return 'A';
end;
/
次に、これら 2 つの関数を使用してデータを選択します。Y
行が 1 つしかないので、 orのみN
が返されることを期待していることを思い出してください。
SQL> -- Expected output Y
SQL> select tmp_ben_fn(1) from dual;
TMP_BEN_FN2(1)
-------------------------------------------------
Y
SQL> -- Expected output, Error no_data_found
SQL> -- as row 2 does not exist.
SQL> select tmp_ben_fn(2) from dual;
TMP_BEN_FN(2)
-------------------------------------------------
SQL> -- Expected output, the same as tmp_ben_fn
SQL> select tmp_ben_fn2(2) from dual;
TMP_BEN_FN2(2)
-------------------------------------------------
A
SQL>
エラー処理のない関数でわかるように、no_data_found
例外が発生すると anull
が返されます。例外をキャプチャすると、A
代わりに期待どおりの結果が得られます。
member_id
選択しようとしている は存在しないと思われます。
原則として、例外が発生する可能性がある場合は常に注意してください。これは、select into...
選択する行が多すぎる場合と行が選択されない場合の特に厄介な例です。テーブルが一意であるmember_id
場合は、関数を次のように変更する必要があります。
CREATE OR REPLACE FUNCTION get_status_by_member_id (p_member_id NUMBER)
RETURN CHAR IS
v_status CHAR(1);
BEGIN
select status
into v_status
from members
where member_id = p_member_id;
return v_status;
-- If the member_id does not exist
-- return N
exception when no_data_found then
return 'N';
END get_status_by_member_id;
次のように、コードに例外ハンドラーを追加してみてください。
CREATE OR REPLACE FUNCTION get_status_by_member_id
(p_member_id NUMBER) RETURN CHAR
as
v_status CHAR(1);
begin
BEGIN
select status
into v_status
from members
where member_id = p_member_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_status := NULL;
WHEN TOO_MANY_ROWS THEN
v_status := NULL;
END;
if v_status is null then
return 'N';
else
return v_status;
end if;
end get_status_by_member_id;
これは、p_member_idに一致するデータがない場合、またはp_member_idに一致する複数の行がある場合を処理します。これにより、発生している問題が修正される場合と修正されない場合があります。投稿を編集して、使用しているコードを追加すると便利ですget_status_by_member_id
。
共有してお楽しみください。