Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Groovy SQL Oracle Array Function/Procedure Out Parameter Registrierung

Ich stand gerade vor dem gleichen Problem und habe jetzt eine Lösung. Grundsätzlich gibt es zwei Probleme. Erstens verlangt Oracle, dass Sie ihm den Namen des Array-Typs mitteilen, wenn der Ausgabeparameter registriert wird. Die zweite ist, wie man Groovy dazu überredet, das zuzulassen. Glücklicherweise scheinen die Groovy-Designer daran gedacht zu haben und Ihnen zu erlauben, groovy.sql.Sql als Unterklasse zu verwenden, um sich in die Parametereinstellung einzuklinken.

Ich werde den Beispieltyp und die gespeicherte Prozedur in dieser Antwort auf eine ähnliche Frage auf JDBC-Ebene verwenden:

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

Jetzt brauchen wir ein paar neue Groovy-Klassen:

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)
        }
    }
}

Die Verwendung dieser ist ziemlich einfach. Wahrscheinlich möchten Sie die Oracle-Dokumentation zu Arrays lesen, um die resultierenden Datenstrukturen zu verstehen.

// 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
    }
}