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

Oracle:キーリストを使用して行を効率的に選択する方法

    INの値を渡すことはお勧めできません 文字列連結としての条件。もちろん、最初はセキュリティと正確さですが、次のポイントはパフォーマンスです。
    ステートメントを呼び出すたびに、データベースエンジンはそれを解析し、クエリプランを作成し、その後SQLステートメントで指定されたアクションを実行します。
    毎回クエリテキストを最初から作成し、3つのステージすべてを毎回実行します。
    ただし、バインド変数を常に使用すると、クエリは同じように見えるため、データベースはキャッシュされたクエリプランを使用してクエリの実行を高速化します。 oci_parse()を呼び出すこともできます 一度だけ、 $ stmtを再利用します 提供されたパラメータのセットが異なる変数。
    したがって、最高のパフォーマンスを得るには、バインド変数を使用し、 oci_bind_array_by_name

    さらに、 oci_fetch_all 結果セットを行ごとに読み取るよりも高速に実行される場合がありますが、結果を処理するロジックによって異なります。

    更新

    配列パラメータの受け渡しは、PL / SQLブロックを実行する場合にのみ機能し、SQL文では使用できないようです。ただし、別の可能性として、コレクション を使用することもできます。 パラメータ値のリストを渡します。配列を使用しても質問の条件を満たすことは可能ですが、この方法はあまり洗練されていません。
    データベースをクエリするさまざまな方法のほかに、システム設定などがあります。 PHPの場合、 php.iniにいくつかのパラメーターがあります。 Oracleとの相互作用を制御するファイル。それらの1つ( oci8.statement_cache_size )クエリのキャッシュとパフォーマンスに関連します。

    すべての例で、Oracleの同じデータ設定を使用しています。
    データを渡すために、事前定義された SYS.ODCIVarchar2Listを選択します。 タイプですが、同じ特性を持つカスタムタイプを定義することもできます(データセットアップの例で示されています)。以下は、データスキームのセットアップとDMLでのコレクションの使用の原則を説明するコードです。

    SQLFiddle

    create table myTable(value varchar2(100), key varchar2(100))
    /
    
    insert into myTable(value, key)
    select * from (
      select 'apple', 'apple_one' from dual union all
      select 'apple', 'apple_two' from dual union all
      select 'banana', 'banana_one' from dual union all
      select 'orange', 'orange_one' from dual union all
      select 'orange', 'orange_two' from dual union all
      select 'potato', 'potato_one' from dual
    )
    /
    
    create or replace type TCustomList as table of varchar2(4000)
    /
    
    create or replace package TestPackage as
    
      type TKeyList is table of varchar2(1000) index by binary_integer;
    
      function test_select(pKeyList in out TKeyList) return sys_refcursor;
    
    end;
    /
    
    create or replace package body TestPackage is
    
      function test_select(pKeyList in out TKeyList) return sys_refcursor
      is               
        vParam sys.ODCIVarchar2List := sys.ODCIVarchar2List();
        vCur sys_refcursor;  
        vIdx binary_integer;
      begin                
    
        vIdx := pKeyList.first;
        while(vIdx is not null) loop
          vParam.Extend;
          vParam(vParam.last) := pKeyList(vIdx);
          vIdx := pKeyList.next(vIdx);
        end loop;
    
        open vCur for 
          select * from myTable where value in (select column_value from table(vParam))    
        ;
    
        return vCur;
      end;
    
    end;
    /
    

    コレクションを示すためのクエリ:

    --select by value list
    select * from myTable 
    where value in (
            select column_value 
            from table(Sys.ODCIVarchar2List('banana','potato'))
          )
    /
    
    --same with custom type
    select * from myTable 
    where value in (
            select column_value 
            from table(TCustomList('banana','potato'))
          )
    /
    
    --same with demonstration of casting 
    select * from myTable 
    where value in (
            select column_value 
            from table(cast(TCustomList('banana','potato') as Sys.ODCIVarchar2List))
          )
    /
    

    例1-コレクションを使用したPHPからの呼び出し

    <?php
      $keyList = array('apple', 'potato');
    
      $conn = oci_pconnect("user_name", "user_password", "SERVER_TNS_NAME");
    
      $stmt = oci_parse($conn, "SELECT * FROM myTable where value in (select column_value from table(:key_list))");
    
      $coll = oci_new_collection($conn, 'ODCIVARCHAR2LIST','SYS');
    
      for ($i=0; $i < count($keyList); $i++) {
        $coll->append($keyList[$i]);
      }
    
      oci_bind_by_name($stmt, 'key_list', $coll, -1, OCI_B_NTY);
    
      oci_execute($stmt);
    
      while($row = oci_fetch_array($stmt, OCI_ASSOC)) {
          echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
      }
      echo "---\n";
    
      $coll->free();
    
      //-- Run statement another time with different parameters
      //-- without reparsing.
    
      $coll = oci_new_collection($conn, 'ODCIVARCHAR2LIST','SYS');
      $coll->append('banana');
      oci_bind_by_name($stmt, 'key_list', $coll, -1, OCI_B_NTY);
    
      oci_execute($stmt);
    
      while($row = oci_fetch_array($stmt, OCI_ASSOC)) {
          echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
      }
      echo "---\n";
    
      $coll->free();
    
      oci_free_statement($stmt);
      oci_close($conn);
    ?>
    

    例2-配列とパッケージを使用してPHPから呼び出す

    <?php
      $keyList = array('apple', 'potato');
    
      $conn = oci_pconnect("user_name", "user_password", "SERVER_TNS_NAME");
    
      $stmt = oci_parse($conn, "begin :cur := TestPackage.test_select(:key_list); end;");
    
      $curs = oci_new_cursor($conn);
    
      oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);
      oci_bind_by_name($stmt, "cur", $curs, -1, OCI_B_CURSOR);
    
      oci_execute($stmt);
      oci_execute($curs);
    
      while($row = oci_fetch_array($curs, OCI_ASSOC)) {
          echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
      }
      echo "---\n";
    
    
      //-- Run statement another time with different parameters
      //-- without reparsing.
    
      $keyList = array('banana');
    
      oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);
    
      oci_execute($stmt);
      oci_execute($curs);
    
      while($row = oci_fetch_array($curs, OCI_ASSOC)) {
          echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
      }
      echo "---\n";
    
      oci_free_statement($stmt);
      oci_close($conn);
    ?>
    

    例3-配列と匿名ブロックを使用したPHPからの呼び出し

    <?php
      $keyList = array('apple', 'potato');
    
      $conn = oci_pconnect("user_name", "user_password", "SERVER_TNS_NAME");
    
      $stmt = oci_parse($conn, "
        declare
          type TKeyList is table of varchar2(4000) index by binary_integer;
    
          pKeyList TKeyList := :key_list;
          vParam   sys.ODCIVarchar2List := sys.ODCIVarchar2List();
          vIdx     binary_integer;
        begin
    
          -- Copy PL/SQL array to a type which allowed in SQL context
          vIdx := pKeyList.first;
          while(vIdx is not null) loop
            vParam.Extend;
            vParam(vParam.last) := pKeyList(vIdx);
            vIdx := pKeyList.next(vIdx);
          end loop;
    
          open :cur for select * from myTable where value in (select column_value from table(vParam));
        end;
      ");
    
      $curs = oci_new_cursor($conn);
    
      oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);
      oci_bind_by_name($stmt, "cur", $curs, -1, OCI_B_CURSOR);
    
      oci_execute($stmt);
      oci_execute($curs);
    
      while($row = oci_fetch_array($curs, OCI_ASSOC)) {
          echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
      }
      echo "---\n";
    
    
      //-- Run statement another time with different parameters
      //-- without reparsing.
    
      $keyList = array('banana');
    
      oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);
    
      oci_execute($stmt);
      oci_execute($curs);
    
      while($row = oci_fetch_array($curs, OCI_ASSOC)) {
          echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
      }
      echo "---\n";
    
      oci_free_statement($stmt);
      oci_close($conn);
    ?>
    


    1. テーブルの行数を取得する最も効率的な方法

    2. PDOは、(特定のテーブル内の)データの行の削除を拒否します

    3. 1つまたは2つの列に基づいて、重複するすべての行を選択しますか?

    4. INSERTINTOテーブルIFテーブルが存在する場合はCREATETABLE