sql >> データベース >  >> RDS >> Oracle

Oracleでパラメータとしてテーブル名を渡すことは可能ですか?

    まったく同じ列名とデータ型を持ついくつかの異なるテーブルがありますか?危険なデザインのようなにおいがします。

    とにかく、そのような単純なSQLではデータベースオブジェクトとして変数を使用することはできません。動的SQLを使用する必要があります。

    PROCEDURE P_CUSTOMER_UPDATE
      (
          pADSLTable IN USER_TABLES.table_name%type,
          pAccountname IN NVARCHAR2,
          pStatus IN NUMBER,
          pNote IN NVARCHAR2,
          pEmail IN NVARCHAR2,
          pMobi IN NVARCHAR2,
          pServiceTypeID IN NUMBER,
          pDate IN DATE
      )
      IS
      BEGIN
          execute immediate 
              'UPDATE '||pADSLTable
              ||' SET STATUS = :1, NOTE = :2, EMAIL = :3, MOBI = :4, SERVICETYPE_ID = :5, ACTIVATION_DATE = :6'
              ||' WHERE ACCOUNT_NAME = :7'
          using pStatus, pNote, pEmail, pMobi, pServiceTypeID, pDate, pAccountname;
      END;
    

    動的SQLの使用を避ける理由の1つは、動的SQLが悪用される可能性があることです。悪意のある人々は、パラメータを使用してセキュリティを回避しようとする可能性があります。これはSQLインジェクションと呼ばれます。人々はSQLインジェクションの重要性を過大評価していると思います。自動的に脅威になるわけではありません。たとえば、プロシージャがパッケージ内のプライベートプロシージャである場合(つまり、仕様で宣言されていない場合)、誰かがそれを乗っ取る可能性はほとんどありません。

    しかし、予防策を講じることは賢明です。 DBMS_ASSERTは、SQLインジェクション攻撃の試みをトラップするためにOracle10gで導入されたパッケージです。この場合、渡されたテーブル名を検証するために使用する価値があります

    ....
    'UPDATE '|| DBMS_ASSERT.simple_sql_name(pADSLTable)
    ....  
    

    これにより、'pay_table set salary = salary * 10 where id = 1234 --'を渡すことができなくなります。 テーブル名パラメータとして。

    動的SQLを回避するもう1つの理由は、正しく取得するのが難しく、デバッグするのが難しいということです。実際のステートメントの構文は、実行時にのみチェックされます。渡されたすべての入力を検証する単体テストの完全なスイートを用意して、プロシージャが構文の例外をスローしないことを確認することをお勧めします。

    最後に、このような動的SQLは、ALL_DEPENDENCIESなどのビューには表示されません。これにより、影響分析を実行し、特定のテーブルまたは列を使用するすべてのプログラムを見つけることが困難になります。



    1. 初心者向けのSQLORDERBY句

    2. SQLServerからのINSERTINTOを使用したSalesforceデータの変更

    3. 結合ステートメント内のMYSQLSelectMAX Date

    4. からOracle11データベースに接続する方法。ネット