2015年11月6日金曜日

PLSQL SELECTの結果を取得する ~取得結果が1行の場合~

今回はPLSQLでSELECTの結果を取得してみます。

下準備としてPLSQL SQL Developer からテーブル作成 で作成したMemberテーブルに3件ほどデータを作成します。
DECLARE 
BEGIN
    INSERT INTO Member
        ( MemberId, MemberName, Rank ) VALUES ( 1, 'Yamada', 'B');
    INSERT INTO Member
        ( MemberId, MemberName, Rank ) VALUES ( 2, 'Tanaka', 'C');
    INSERT INTO Member
        ( MemberId, MemberName, Rank ) VALUES ( 3, 'Suzuki', 'A');
END;

それではデータを1件抽出し変数に代入します。
DECLARE部でデータを代入する変数を宣言します。
次に「SELECT 列名 INTO 代入する変数」で取得したデータを変数に代入します。
データが取得できない場合や複数件取得できた場合はエラーになるので注意してください。
DECLARE
    memberid VARCHAR2(4);
    membername VARCHAR2(10);
    rank VARCHAR2(2);
BEGIN
    SELECT MemberId, MemberName, Rank INTO memberid, membername, rank
    FROM Member
    WHERE MemberId = '1';
    
    SYS.DBMS_OUTPUT.PUT_LINE('MemberId:' || memberid);
    SYS.DBMS_OUTPUT.PUT_LINE('MemberName:' || membername);
    SYS.DBMS_OUTPUT.PUT_LINE('Rank:' || rank);
END;
上記の例では変数のデータ型をSELECTで取得する列のデータ型と合わせる必要がありました。
memberid VARCHAR2(4);の「VARCHAR2(4)」部分です。
だけどイチイチ列のデータ型や精度を指定するのはメンドクサイよ!
仕様変更でデータ型や精度が変わるたびに修正するのはメンドクサイよ!
メンドクサイのはイヤなので上記の変数宣言のデータ型を「%type属性」を使用してちょっとラクします。
DECLARE
    memberid Member.MemberId%type;
    membername Member.MemberName%type;
    rank Member.Rank%type;
BEGIN
    SELECT MemberId, MemberName, Rank INTO memberid, membername, rank
    FROM Member
    WHERE MemberId = '1';
    
    SYS.DBMS_OUTPUT.PUT_LINE('MemberId:' || memberid);
    SYS.DBMS_OUTPUT.PUT_LINE('MemberName:' || membername);
    SYS.DBMS_OUTPUT.PUT_LINE('Rank:' || rank);
END;
Oracle Database PL/SQL言語リファレンスによりますと
『%TYPE属性を使用すると事前に宣言されている変数、フィールド、レコード、ネストした表またはデータベース列と同じデータ型の定数、変数、フィールドまたはパラメータを宣言できます。参照先項目が変更されると、宣言は自動的に更新されます。』とあります。

つまり「memberid Member.MemberId%type;」の部分は
MemberテーブルのMemberId列と同じデータ型にし、MemberテーブルのMemberId列のデータ型が変更されても自動的に変更するから大丈夫ということです。

う~ん
でもまだメンドクサイ。Memberテーブルの1データを取得するのに、Memberテーブルに含まれるすべての列分の変数を作るのはメンドクサイよ。
Memberテーブルの列が20列ぐらいあったら、変数も20個用意するの・・・・?ムリ。

ハイ!そんなときは「%ROWTYPE属性」を使用します。
DECLARE
    member_rec Member%rowtype;
BEGIN
    SELECT * INTO member_rec
    FROM Member
    WHERE MemberId = '1';
    
    SYS.DBMS_OUTPUT.PUT_LINE('MemberId:' || member_rec.MemberId);
    SYS.DBMS_OUTPUT.PUT_LINE('MemberName:' || member_rec.MemberName);
    SYS.DBMS_OUTPUT.PUT_LINE('Rank:' || member_rec.Rank);
END;
「レコード変数名 表名%ROWTYPE;」とすることでテーブルの1データを代入できる変数ができるんですね!
ステキです。

ステキですね~ラクですね~使いまくりたくなりますね~

でもダメなんですね~

今回Memberテーブルは3列しかないですが、Memberテーブルが20列あったとします。
そのうち使用するのは5列だったとしたら、15列分のデータは取得するけど無駄になってしまいます。

そんな場合は、使用する列だけのレコード型を自分で定義し、必要な列だけ変数に代入するようにします。
DECLARE
    --レコード型の作成
    TYPE member_rec_type IS RECORD
        (
            MemberId  Member.MemberId%type,
            MemberName  Member.MemberName%type
        );
    --レコード型のレコード変数を宣言
    member_rec member_rec_type;
BEGIN
    SELECT MemberId, MemberName INTO member_rec
    FROM Member
    WHERE MemberId = '1';
    
    SYS.DBMS_OUTPUT.PUT_LINE('MemberId:' || member_rec.MemberId);
    SYS.DBMS_OUTPUT.PUT_LINE('MemberName:' || member_rec.MemberName);
END;
「TYPE データ型名 IS RECORD (フィールド宣言・・・);」でレコードの「型」を宣言します。
次にデータ型が作成したレコード型の変数を宣言します。

レコード型を作成するのがメンドクサイですが、使い分けが必要なようです。

0 件のコメント: