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

GroovySQLOracle配列関数/プロシージャアウトパラメータの登録

    私はちょうど同じ問題に直面し、今解決策を持っています。基本的に2つの問題があります。 1つ目は、出力パラメータを登録するときに、Oracleが配列型の名前を指定するように要求することです。 2つ目は、Groovyにそうさせる方法です。幸い、Groovyの設計者はこれを考えており、groovy.sql.Sqlをサブクラス化してパラメーター設定にフックできるようになっているようです。

    JDBCレベルでの同様の質問に対するこの回答では、サンプルタイプとストアドプロシージャを使用します。

    SQL> CREATE TYPE t_type AS OBJECT (val VARCHAR(4));
    2  /
    Type created
    
    SQL> CREATE TYPE t_table AS TABLE OF t_type;
    2  /
    Type created
    
    SQL> CREATE OR REPLACE PROCEDURE p_sql_type (p_out OUT t_table) IS
    2  BEGIN
    3     p_out := t_table(t_type('a'), t_type('b'));
    4  END;
    5  /
    Procedure created
    

    ここで、いくつかの新しいGroovyクラスが必要です。

    import groovy.sql.*
    import java.sql.CallableStatement
    import java.sql.PreparedStatement
    import java.sql.SQLException
    import oracle.jdbc.driver.*
    
    class OracleArrayOutParameter implements OutParameter {
        String typeName
    
        int getType() {
            OracleTypes.ARRAY
        }
    }
    
    class OracleArrayAwareSql extends Sql {
    
        OracleArrayAwareSql(Sql parent) {
            super(parent)
        }
    
        void setObject(PreparedStatement statement, int i, Object value) throws SQLException {
            if (value instanceof OracleArrayOutParameter) {
                try {
                    OracleArrayOutParameter out = (OracleArrayOutParameter) value;
                    ((CallableStatement) statement).registerOutParameter(i, out.getType(), out.typeName);
                } catch (ClassCastException e) {
                    throw new SQLException("Cannot register out parameter.");
                }
            }
            else {
                super.setObject(statement, i, value)
            }
        }
    }
    

    これらの使用法は非常に簡単です。おそらく、配列に関するOracleのドキュメントで、結果のデータ構造を理解する必要があります。

    // First create a "normal" groovysqlSql instance, using whatever method you like
    
    def parent = Sql.newInstance("jdbc:oracle:thin:@host:port:sid", "user", "password", "oracle.jdbc.OracleDriver")
    
    // Then create an OracleArrayAwareSql instance giving that parent instance as a parameter
    
    def sql = new OracleArrayAwareSql(parent)
    
    // Now define an OracleArrayOutParameter naming the array type
    
    def tTableParam = new OracleArrayOutParameter(typeName: 'T_TABLE')
    
    // And make a stored procedure call as usual
    
    sql.call("{call p_sql_type(${tTableParam})}") { out ->
    
        // The returned parameter is of type oracle.sql.ARRAY
    
        out.array.each { struct ->
            println struct.attributes
        }
    }
    



    1. あなたを驚かせるかもしれないデータベースパフォーマンスモニタリングについての10の事実

    2. 単一のexecSQLクエリで指定できるSQL変数の制限は何ですか

    3. Perconaサーバーをハイブリッドクラウドにデプロイする

    4. 自動インクリメント主キーの並べ替え/リセット