Groovy SQL Oracle 数组函数/过程输出参数注册

2024-03-20

我无法确定在使用存储的函数/过程时如何描述/注册数组输出参数。我需要传递多个数组输出参数以利用 Oracle 数据库中的 api。将参数中的数组发送到存储的函数/过程以及选择数组类型的单列到结果集中都有效。

我认为在这种情况下,需要使用数据库嵌套表类型 NUMBERS_T 来定义 Array out 参数。但我无法找到如何使用 Groovy Sql 类定义这种关系。

请查看下面的代码,其中包含所需的设置,然后执行有效的操作以及注释掉发生故障的区域以及相应的错误消息。任何帮助将不胜感激。

import groovy.sql.Sql  // groovy v2.4.5
import oracle.jdbc.pool.OracleDataSource  // ojdbc6.jar v11.2.0.4

def dataSource = new oracle.jdbc.pool.OracleDataSource (URL: 'jdbc:oracle:thin:@myServer:1521/myService', user: 'myAccount', password: 'myPassword')
def sql = new Sql (dataSource)


/*** begin array test setup ...
sql.execute """\
  create type numbers_t as table of number;
"""
sql.execute """\
  create table numbers_tab (
    value number
  )
"""
sql.execute """\
  create or replace procedure insert_numbers_proc (p_numbers numbers_t) is
  begin
    for iterator in 1 .. p_numbers.count () loop
      insert into numbers_tab (value) values (p_numbers (iterator));
    end loop;
    commit;
  end insert_numbers_proc;
"""
sql.execute """\
  create or replace function select_numbers_func return numbers_t is
    l_result numbers_t;
  begin
    select value bulk collect into l_result from numbers_tab;
    return l_result;
  end select_numbers_func;
"""
sql.execute """\
  create or replace procedure select_numbers_proc (p_numbers out numbers_t) is
  begin
    select value bulk collect into p_numbers from numbers_tab;
  end select_numbers_proc;
"""
... end of array test setup ***/

def numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5] as Object[]

def pArray = sql.dataSource.connection.createARRAY 'NUMBERS_T', numbers
sql.call "{call insert_numbers_proc ($pArray)}"

def sqlRow_1 = sql.firstRow "select select_numbers_func () as select_results from dual"
println "Class: ${sqlRow_1.select_results.getClass ().name}, Values: ${sqlRow_1.select_results.array}"
//output= Class: oracle.sql.ARRAY, Values: [3, 1, 4, 1, 5, 9, 2, 6, 5]

def sqlRow_2 = sql.firstRow "select cast (multiset (select value from numbers_tab) as numbers_t) as select_results from dual"
println "Class: ${sqlRow_2.select_results.getClass ().name}, Values: ${sqlRow_2.select_results.array}"
//output= Class: oracle.sql.ARRAY, Values: [3, 1, 4, 1, 5, 9, 2, 6, 5]


/*** all of these failt ...

sql.call ("{call ${Sql.ARRAY} := select_numbers_func ()}") { result_1 -> println result_1.getClass ().name }
groovy.sql.Sql callWithRows
WARNING: Failed to execute: {call ? = select_numbers_func ()} 
because: ORA-03115: unsupported network datatype or representation

sql.call ("{call select_numbers_proc (${Sql.ARRAY})}") { result_2 -> println result_2.getClass ().name }
groovy.sql.Sql callWithRows
WARNING: Failed to execute: {call select_numbers_proc (?)}
because: ORA-03115: unsupported network datatype or representation

sql.call ("{call ${oracle.sql.ARRAY} := select_numbers_func ()}") { result_3 -> println result_3.getClass ().name }
groovy.sql.Sql callWithRows
WARNING: Failed to execute: {call ? = select_numbers_func ()} 
because: Invalid column type

sql.call ("{call select_numbers_proc (${oracle.sql.ARRAY})}") { result_4 -> println result_4.getClass ().name }
groovy.sql.Sql callWithRows
WARNING: Failed to execute: {call select_numbers_proc (?)}
because: Invalid column type
***/

我刚刚遇到了同样的问题,现在有了解决方案。基本上有两个问题。首先,Oracle 要求您在注册输出参数时告诉它数组类型的名称。第二个是如何说服 Groovy 让你这样做。幸运的是,Groovy 设计者似乎想到了这一点,并允许您对 groovy.sql.Sql 进行子类化以挂钩参数设置。

我将使用示例类型和存储过程这是 JDBC 级别类似问题的答案 https://stackoverflow.com/questions/6410452/fetch-oracle-table-type-from-stored-procedure-using-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 文档 https://docs.oracle.com/cd/B28359_01/java.111/b31224/oraarr.htm了解生成的数据结构。

// 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
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Groovy SQL Oracle 数组函数/过程输出参数注册 的相关文章

随机推荐

  • PasswordResetsController#update 中的 ActiveModel::ForbiddenAttributesError

    我看过 Ryan 铁路广播第 274 集 我正在使用 Rails 4 并遇到一个问题 在password resets controller rb中 elsif user update attributes params user 在控制台
  • 触摸屏设备上的 HTML5 拖放 API

    我只是想知道用于拖放的 HTML5 API 是否包含对触摸屏显示的支持 我正在考虑 iPhone 但我知道它还不支持 我想知道苹果是否正在追赶 以支持 Safari 移动设备上的 HTML5 拖放 但我也想也许 HTML5 API 对此不够
  • 不使用 HQL 检索表的所有行?

    我正在使用 Hibernate 4 并且想简单地列出表的所有行 我发现的所有解决方案都建议使用 from tablename 之类的内容 但我想避免在字符串中硬编码表名 您可以使用 session createCriteria MyEnti
  • 如何让FlashDevelop使用32位JRE?

    我需要为 Android Studio 安装 64 位 JDK 这也意味着JAVA HOME设置为 64 位 JDK 我还安装了 32 位 JRE 和 Flex SDKjvm config文件我指定了它的路径 我知道 Flex SDK 使用
  • 声明FigureCanvasTkAgg导致内存泄漏

    我很难弄清楚为什么FigureCanvasTkAgg 的声明会导致内存泄漏 我的类中有以下几行 init method pndwinBottom is a paned window of the main screen self drawp
  • 获取存在多个相同值的行[重复]

    这个问题在这里已经有答案了 我有一个 R 数据框 看起来像这样 A B C 14 apple 45 14 bannaa 23 15 car 234 16 door 12 16 ear 325 正如您所看到的 14 和 16 是重复的 我想
  • 通用 DataRow 扩展

    我使用扩展方法来检查 DataRowField 是否为 null public static string GetValue this System Data DataRow Row string Column if Row Column
  • 如何使用 Dapper 扩展谓词实现“NOT IN”子句?

    我找到了如何实施IN使用 Dapper 扩展的子句here https stackoverflow com questions 49777139 how to implement in clause with dapper extensio
  • 临时 ASP.NET 文件丢失

    在我的asp项目中运行时抛出错误 昨天效果很好 但今天早上它自己给出了以下消息 Could not load file or assembly file C Windows Microsoft NET Framework v4 0 3031
  • 如何在单个事务下执行多个操作

    我有一个场景 需要将记录添加到表中 然后 如果添加了记录 则在云上创建资源 如果在云上创建资源 则使用资源标识符更新表中的记录 所以 它们是 3 个操作 当其中任何一个操作不成功时 我想恢复所有操作 我们一次性拥有用于多个数据库操作的 Tr
  • 如何调试我的 JavaScript 代码? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 当我发现我的代码片段有问题时 我应该如何调试它 Firebug http en wikipedia org wiki Firebug
  • jQuery/css/html:具有固定标题的可滚动表格[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我知道这个问题已经被问过好几次了 但我还找不到令人满意的 x 浏览器解决方案 我认为完成具有固定标题的可滚动表格的最简单方法应该是使用
  • SLF4J - 什么是悬挂或分离标记?

    在 SLF4J 中我不完全确定什么是分离标记 http www slf4j org apidocs org slf4j IMarkerFactory html getDetachedMarker 28java lang String 29是
  • 以编程方式确定 Android Wear 中的屏幕形状

    我正在寻找一种技术来确定 Java 中 Android Wear 设备屏幕是圆形还是矩形 请注意 这不仅仅涉及布局 还涉及布局 我的代码实际上需要知道它正在使用哪种形状 因为它们的处理方式不同 据我从在线代码示例中看到 两种不同的方法应该是
  • 我如何知道我的神经网络模型是否过度拟合(Keras)

    我使用 Keras 来预测输出是 1 还是 0 数据如下所示 funded amnt emp length avg cur bal num actv rev tl loan status 10000 5 60088 19266 2 1 13
  • 针对只读对象模型的 SqlAlchemy 优化

    我有一个复杂的对象网络 这些对象是使用 sqlalchemy ORM 映射从 sqlite 数据库生成的 我有很多深层嵌套 for parent in owner collection for child in parent collect
  • php mysql 错误 - #1273 - #1273 - 未知排序规则:'utf8mb4_general_ci'

    我刚刚安装了 PhpMyAdmin v4 1 5 仅英文版 我已将其设置为访问 2 台服务器 我的 PC 上的本地服务器和我的服务器上的远程服务器 对于我的本地电脑来说一切都很好 但是当我登录到远程服务器时 我收到了消息 Error MyS
  • 如何从 T-SQL 中的字符串中删除扩展 ASCII 字符?

    我需要从 T SQL 中的 SELECT 语句中过滤 删除 扩展 ASCII 字符 我正在使用存储过程来执行此操作 预期输入 eeee 预期输出 eeee 我所找到的一切都是为了MySQL https forums oracle com f
  • 如何使用 php 检查 smtp 服务器是否正常工作

    我想使用 php 检查我的网站 smtp 是关闭还是开启 我尝试使用 fsockopen 连接到服务器上的端口 25 然后当 smtp 服务运行时它返回 true 这是使用 php 脚本测试 smtp 或 ftp 是否运行的最佳方法 您正在
  • Groovy SQL Oracle 数组函数/过程输出参数注册

    我无法确定在使用存储的函数 过程时如何描述 注册数组输出参数 我需要传递多个数组输出参数以利用 Oracle 数据库中的 api 将参数中的数组发送到存储的函数 过程以及选择数组类型的单列到结果集中都有效 我认为在这种情况下 需要使用数据库