PL/SQLの勉強8 データを1件だけ取得する
PL/SQLでプログラムを組んでいると
データを1件だけ取得して変数に持ちたいな〜
なんて思うことがあります。
そんな時はどうやるのか…
今回はそれをやっていきましょう。
まずはサンプルのデータを用意
そんなのいらないよ!
と言う方は、次に行ってくださいw
こんな感じのデータを用意しますよ。
ID | NAME |
---|---|
1 | 太郎 |
2 | 花子 |
3 | 光宙 |
以下のDDL・DMLを全部コピーして
Oracle Live SQLに貼り付け・実行すれば
自分で試すためのデータは用意できますよ♪
create table COMMON_MST
(
ID number
,NAME varchar2(4000)
,constraint PK_COMMON_MST primary key (ID)
)
;
insert into COMMON_MST values (1, '太郎');
insert into COMMON_MST values (2, '花子');
insert into COMMON_MST values (3, '光宙');
commit;
試しにちゃんとデータが入っているか
確認してみましょう。
select
*
from COMMON_MST
;
大丈夫そうですね!
これでデータの準備はOKです。
データを1件だけ取得
まずは結論をば。。。
こんな感じに書きますよ!
declare
v_name varchar2(4000);
begin
select
NAME
into
v_name
from COMMON_MST
where ID = 1
;
dbms_output.put_line('取得した名前 : ' || v_name);
end;
実行結果はこんな感じになるはずです。
「太郎」が取得できていますね!
詳しく見ていきましょう。
普通のSELECT文ではないですね。
7行目に「into」があります!
人がテーブルからデータを取得するときは
「どんなデータが入っているの?」
って見るだけですが
プログラムがデータを取得するときは
「そのデータを変数に持って、その後で何かに使う!」
となるはずです。
何かに使うためにデータを取得したんでしょ?
それを後で使うために、変数に保持しておかないと!
…という感じ♪
ちなみに…
変数に持たないでSELECTするだけ!
なんてことは出来ません。
エラーになります。
エラーメッセージを見ると
「SELECTするときはINTOが必要だよ!」
って言われてますね。
もっとプログラムの堅牢化を目指した形
例えば以下のプログラムを書いてしまうと、エラーになります。
declare
v_name varchar2(1);
begin
select
NAME
into
v_name
from COMMON_MST
where ID = 1
;
dbms_output.put_line('取得した名前 : ' || v_name);
end;
「character string buffer too small」
って書いてありますね。
2行目の変数を定義するところで
「varchar2(1)」と書いている。。。
つまり、変数は1byteまでしか入れられないのに
「太郎」という文字を入れようとして
そんなに大きいデータは入らないよ〜!と言われているんです。
何byteか考えながら変数を定義しないといけないの?
めんどくせー!!
と思う方、センスあります!
簡単な方法があるんです!
declare
v_name COMMON_MST.NAME%type;
begin
select
NAME
into
v_name
from COMMON_MST
where ID = 1
;
dbms_output.put_line('取得した名前 : ' || v_name);
end;
結果は上と同じで「太郎」が取得できます。
注目すべきは2行目!
「COMMON_MST.NAME%type;」と書いてますね。
COMMON_MSTというテーブルの
NAMEというカラムの
type、つまり定義を使うよ!
と言っています。
これを使えば
テーブル定義とかあまり考えなくても
プログラム書けちゃいますね♪
一気に複数カラムのデータを取得
あくまでも「このやり方は」
1行のデータしか取得できません。
けど1行であれば
複数カラムの取得は可能です!
こんな感じに書けますよ。
declare
v_id COMMON_MST.ID%type;
v_name COMMON_MST.NAME%type;
begin
select
ID
,NAME
into
v_id
,v_name
from COMMON_MST
where ID = 1
;
dbms_output.put_line('取得したID:' || v_id || ', 名前 : ' || v_name);
end;
名前だけじゃなくてIDも追加してみました。
結果はこんな感じです。
ちゃんと取れてますね!
「v_id」という変数も
どんなデータ型なのか考えないでも書けちゃいます♪
変数をいくつも書くのが面倒な人は…
こんな書き方も出来ますよ!
declare
v_common_mst COMMON_MST%rowtype;
begin
select
*
into
v_common_mst
from COMMON_MST
where ID = 1
;
dbms_output.put_line('取得したID:' || v_common_mst.ID || ', 名前 : ' || v_common_mst.NAME);
end;
注目するのは2行目。
今までは「<テーブル名>.<カラム名>%type」だったのが
今回は「<テーブル名>%rowtype」ってなってますね!
SELECTではカラム名を書かないで「*」としています。
データを使う(出力)する時には
「v_common_mst.ID」とか「v_common_mst.NAME」
ってしています。
ID・NAMEはテーブルのカラムに該当します。
こういうやり方はありますが
僕は実際には使ったことないです。後で見た時 or 他の誰かがこれを見た時、
「このテーブルにはどんなカラムがあるの?」
が一目では分からないからです。いちいちテーブル定義を見に行くのが面倒!!
この地味な一手間が積み重なると
読みにくいプログラムが出来上がるのです。。。
なので、100歩譲ってこんな感じに書くとしたら…
こうでしょうか。
declare
v_common_mst COMMON_MST%rowtype;
begin
select
ID
,NAME
into
v_common_mst
from COMMON_MST
where ID = 1
;
dbms_output.put_line('取得したID:' || v_common_mst.ID || ', 名前 : ' || v_common_mst.NAME);
end;
6行目が「*」から
ID・NAMEって変わってるだけですが
「どんなテーブル定義なの?」
という苦痛は解消されます。
ただし注意が必要です!
この書き方、SELECT句のカラムは
テーブル定義通りに・同じ順番で書く必要があります。
じゃないとエラーになります。
エラーに注意してね!
「1件だけ取得する方法」
としてやっていますが、
ちょっと間違えるとエラーとなってしまいます。
なので注意してね!
というお話もしておこうと思います。
複数の行を取得しようとするとエラーになるよ
複数のデータを取得しようとした場合…
こうなります。
declare
v_id COMMON_MST.ID%type;
v_name COMMON_MST.NAME%type;
begin
select
ID
,NAME
into
v_id
,v_name
from COMMON_MST
where ID > 1
;
dbms_output.put_line('取得したID:' || v_id || ', 名前 : ' || v_name);
end;
WHERE句が「1より大きい」ってなってます。
この場合、結果は2行返ってきます。
エラーになってしまいましたね!
こうならないために、プログラムを書くときは
必ず1件しか取得できないことを担保するべきです。
どうやって担保するか…?
簡単です。
テーブル定義でprimary key(主キー)って
なっていることを確認すればいいんです!
0件でもエラーになるよ
SELECTした結果が0件でもエラーになります。
IDが4のデータは無いので
データは取得できません。
こちらも注意が必要ですね!
結局、僕はどう書くのか?
僕だったらこう書きます。
これ1択です!
declare
v_id COMMON_MST.ID%type;
v_name COMMON_MST.NAME%type;
begin
select
ID
,NAME
into
v_id
,v_name
from COMMON_MST
where ID = 1
;
dbms_output.put_line('取得したID:' || v_id || ', 名前 : ' || v_name);
end;
以上ですw
1行だけデータを取得する場合について
やっていきました。
ちょっと注意する点はありますが
実際に仕事する際にも使える手法です。
「とあるテーブルに固定値が入っている
ので、それを取得したい!」
って時によく使います。
次回は、複数データを取得する場合…
についてやっていきます!
Discussion
New Comments
No comments yet. Be the first one!