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

テーブルに存在しないINリストの要素に対しても結果を返します

    SQL側からは、テーブルタイプを定義し、それを使用して実際のデータに結合できます。たとえば、次のようになります。

    create type my_array_type as table of number
    /
    
    create or replace function f42 (in_array my_array_type)
    return sys_refcursor as
      rc sys_refcursor;
    begin
      open rc for
        select a.column_value as id,
          case when t.id is null then 'missing'
            else 'present' end as status
        from table(in_array) a
        left join t42 t on t.id = a.column_value
        order by id;
    
      return rc;
    end f42;
    /
    

    ラッパー関数を使用したSQLFiddleデモ。直接クエリを実行できるため、次のようになります。

            ID STATUS             
    ---------- --------------------
             1 present              
             2 present              
             3 present              
             4 missing              
             8 missing              
            23 present              
    

    Javaから、ARRAYを定義できます。 テーブルタイプに基づいて、Java配列からデータを入力し、関数を直接呼び出します。単一のパラメーターバインド変数はARRAYです 、そして結果セットが返され、通常どおりに繰り返すことができます。

    Java側の概要として:

    int[] ids = { 1, 2, 3, 4, 8, 23 };
    ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("MY_ARRAY_TYPE",
      conn);
    oracle.sql.ARRAY ora_ids = new oracle.sql.ARRAY(aDesc, conn, ids);
    
    cStmt = (OracleCallableStatement) conn.prepareCall("{ call ? := f42(?) }");
    cStmt.registerOutParameter(1, OracleTypes.CURSOR);
    cStmt.setArray(2, ora_ids);
    cStmt.execute();
    rSet = (OracleResultSet) cStmt.getCursor(1);
    
    while (rSet.next())
    {
        System.out.println("id " + rSet.getInt(1) + ": " + rSet.getString(2));
    }
    

    与えるもの:

    id 1: present
    id 2: present
    id 3: present
    id 4: missing
    id 8: missing
    id 23: present
    

    Maheswaran Ravisankarが言及しているように、これにより、任意の数の要素を渡すことができます。コンパイル時に要素がいくつあるかを知る必要はありません(または理論上の最大値を処理する必要はありません)。INで許可される式の最大数に制限されません。 または、1つの区切られた文字列の長さで、複数の値を渡すために文字列を作成および分解する必要はありません。

    ThinkJetが指摘したように、独自のテーブルタイプを作成したくない場合は、ここで示す事前定義されたコレクションを使用できます。パラメータの宣言を除けば、主な機能は同じです:

    create or replace function f42 (in_array sys.odcinumberlist)
    return sys_refcursor as
    ...    
    

    ラッパー関数は配列にわずかに異なる方法でデータを入力しますが、Java側では、次の行を変更するだけで済みます。

    ArrayDescriptor aDesc =
      ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );
    

    これを使用すると、(ThinkJetも指摘したように)関数を定義せずに元のスタンドアロンクエリを実行できることも意味します。

    select a.column_value as id,
    case when t.id is null then 'missing'
    else 'present' end as status
    from table(sys.odcinumberlist(1, 2, 3, 4, 8, 23)) a
    left join t42 t on t.id = a.column_value
    order by id;
    

    (SQLフィドル)。

    つまり、Javaから直接クエリを呼び出すことができます:

    int[] ids = { 1, 2, 3, 4, 8, 23 };
    ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );
    oracle.sql.ARRAY ora_ids = new oracle.sql.ARRAY(aDesc, conn, ids);
    
    sql = "select a.column_value as id, "
        + "case when t.id is null then 'missing' "
        + "else 'present' end as status "
        + "from table(?) a "
        + "left join t42 t on t.id = a.column_value "
        + "order by id";
    pStmt = (OraclePreparedStatement) conn.prepareStatement(sql);
    pStmt.setArray(1, ora_ids);
    rSet = (OracleResultSet) pStmt.executeQuery();
    
    while (rSet.next())
    {
        System.out.println("id " + rSet.getInt(1) + ": " + rSet.getString(2));
    }
    

    ...あなたが好むかもしれません。

    事前定義されたODCIVARCHAR2LISTがあります 実際に文字列を渡す場合も入力します。元のコードは、数字が含まれていても文字列を処理しているように見えるため、本当に必要なものがわからない場合があります。

    これらのタイプはVARRAY(32767)として定義されているため 独自のテーブルを定義するとその制限がなくなりますが、32kの値に制限されます。しかし、明らかにそれは、多くの値を渡す場合にのみ重要です。



    1. ランダムな結果を10個取得するためにwhile/loopを実行する

    2. ハイブリッドクラウドPostgreSQLの導入のヒント

    3. DBMS_JOBとDBMS_SCHEDULER

    4. TypeORMサブクエリ