[ Oracle PL/SQL ] バインド変数を使用してセキュアに SQL を実行する

Pocket

C# や Java などのプログラムから SQL を実行するときはバインド変数を使用して SQL インジェクション対策を行い、データを守るようにすることが一般的だと思いますが、Oracle データベース上で実行される PL / SQL から SQL を発行するときも同様です。Oracle が勝手に対策してくれるわけではありません。

スポンサーリンク

また、「ヘッポコプログラマが一般論を語るな!」という指摘は心が痛みます。きっと的確な指摘なのでしょう。

参照系サンプル
CREATE OR REPLACE PROCEDURE TEST_PROCEDURE(pDeptCd VARCHAR2)
IS
  vSql  VARCHAR2(1024); -- SQL格納バッファ
  type cur_emp_type is ref cursor;  -- カーソル変数のオブジェクト定義
  cur_emp cur_emp_type;             -- カーソル変数定義
    
  user_rcd  test_user_mst%rowtype;  -- ユーザーマスターテーブルのレコード変数
BEGIN

  /*
   * カーソル変数オープン
   * プロシージャのパラメータをバインドしている。
   * バインド変数名(:dept_cd)は何でも良いが、人が理解できるようにつける
   */
  open cur_emp for 'select * from test_user_mst where dept_cd = :dept_cd' using pDeptCd;

  loop
    -- 取得したレコードをを変数に代入。
    fetch cur_emp into user_rcd;

    -- レコードの終了を判定する
    exit when cur_emp%notfound;

    -- 取得したレコードからのカラムを出力する
    -- ドット(.)でレコード変数とカラム名を連結して指定する
    dbms_output.put_line('ユーザーコード:' || user_rcd.test_user_cd);
    dbms_output.put_line('ユーザー名    :' || user_rcd.test_user_name);

  end loop;

END;
/
更新系サンプル
CREATE OR REPLACE PROCEDURE TEST_PROCEDURE(
                                    pCd   VARCHAR2,  -- パラメータ1
                                    pName VARCHAR2)  -- パラメータ2
IS
    vSql  VARCHAR2(1024); -- SQL 格納バッファ
BEGIN
    /*
     * SQLを作成する。バインド変数は :CDと:NAMEである。
     * 名前に意味はないが、わかりやすい名称を使用する
     */        
    vSql := 'insert into test_table(CD, NAME) values(:CD, :NAME)';

    /*
     * EXECUTE IMMEDIATE で SQLを実行し、USING IN でバインド変数に
     * 値を設定している。
     */       
    EXECUTE IMMEDIATE vSql USING IN pCd, pName;

    -- Insertした件数を取得。Update文であれば、更新したレコード数
    DBMS_OUTPUT.PUT_LINE('インサート件数 : ' || SQL%ROWCOUNT || '件');

    -- コミット(必要であれば)する。
    -- トランザクションの制御は外部で行うことも多いだろう
    COMMIT;
END;
/

 

スポンサーリンク


Pocket

Leave a Comment

Your email address will not be published. Required fields are marked *