当前位置: 首页 > 知识库问答 >
问题:

我无法使用jdbc调用该函数,但如果它是流水线的,那么一切都可以正常工作

郭均
2023-03-14

我使用Spring jdbc和oracle 12。

我无法从package函数获得响应。但如果我使用完全相同的函数,但使用管道,一切都会正常。

创建了一个包并在其中声明了2个函数。它们都以一个数字作为输入,并输出一个pl/sql记录表。函数的不同之处在于,一个是流水线的,另一个不是

该宣言是:

type o_client is record(subs_id     NUMBER);
type t_client is table of o_client;
    
function piplined_func   (p_subs_id in NUMBER)  return t_client pipelined;

function no_piplined_func   (p_subs_id in NUMBER)  return t_client;

主体为:

function piplined_func(p_subs_id in NUMBER) return t_client PIPELINED AS 
v_pipe o_client;
BEGIN 
    FOR ids IN 1..10 LOOP
        v_pipe.subs_id := ids;
        PIPE ROW(v_pipe); 
    END LOOP;
    return ;
END;

function no_piplined_func   (p_subs_id in number)  return t_client  AS 
    l_tab t_client;
    v_pipe o_client;
BEGIN
    l_tab := t_client();
    FOR ids IN 1..10 LOOP
        v_pipe.subs_id := ids;
        l_tab.extend;
        l_tab(l_tab.last) := v_pipe;
    END LOOP;
    return l_tab;
END;

第一个功能是工作正确:

System.out.println("Pipelined");
Processor processor = new Processor(oracleDataSource);
final String query = "select * MY_CATALOG.piplined_func(:p_subs_id)";
SqlParameterSource inputParams = new MapSqlParameterSource().addValue("p_subs_id", 1);
List<Wrapper> result = namedParameterJdbcTemplate.query(query, inputParams, BeanPropertyRowMapper.newInstance(Wrapper.class));
for (Wrapper wrapper : result) {
    System.out.println(wrapper.toString());
}
Out:
Wrapper{subs_id=1}
Wrapper{subs_id=2}
Wrapper{subs_id=3}

第二个函数工作不正确:

System.out.println("Not Pipelined");
Processor processor = new Processor(oracleDataSource);
final String query = "select * from MY_CATALOG.no_piplined_func(:p_subs_id)";
SqlParameterSource inputParams = new MapSqlParameterSource().addValue("p_subs_id", 1); 
List<Wrapper> result = namedParameterJdbcTemplate.query(query, inputParams, BeanPropertyRowMapper.newInstance(Wrapper.class));
for (Wrapper wrapper : result) {
    System.out.println(wrapper.toString());
}

组织。springframework。jdbc。BadSqlGrammarException:PreparedStatementCallback;错误的SQL语法[从sa\U db\U测试中选择*无管道功能(?);嵌套异常为java。sql。SQLSyntaxErrorException:ORA-00902:无效的数据类型

我尝试以同样的方式使用SimpleJDBCall,但也没有成功。

SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(oracleDataSource)
    .withSchemaName("MY_SCHEMA")
    .withCatalogName("MY_CATALOG")
    .withProcedureName("no_piplined_func")
    .withoutProcedureColumnMetaDataAccess()
    .declareParameters( new SqlParameter("p_subs_id", Types.NUMERIC),);
SqlParameterSource in = new MapSqlParameterSource().addValue("p_subs_id", 1);
Map<String, Object> out = simpleJdbcCall.execute(in);

线程“main”组织中出现异常。springframework。jdbc。BadSqlGrammarException:CallableStatementCallback;错误的SQL语法[{调用MY\u SCHEMA.MY\u CATALOG.NO\u PIPLINED\u FUNC(?)}];嵌套异常为java。sql。SQLException:ORA-06550:第1行,第7列:PLS-00221:“NO\u PIPLINED\u FUNC”不是过程或未定义

共有1个答案

仇建茗
2023-03-14

记录是仅限PL/SQL的数据类型,不能在SQL语句中使用。

管道化函数设计用于SQL语句中,尽管您声明它返回一个包含数据类型的表,但它实际上并没有这样做,而是创建可以在SQL语句中使用的等效SQL数据类型(即对象数据类型)。

如果您希望两者都起作用,请在SQL范围内声明o_clientt_client,使用:

CREATE TYPE o_client IS OBJECT (subs_id NUMBER);
CREATE TYPE t_o_client IS TABLE OF o_client;

然后,您可以使用SQL数据类型而不是PL/SQL数据类型:

CREATE PACKAGE pkg IS
  type r_client is record(subs_id     NUMBER);
  type t_client is table of r_client;
    
  function pipelined_func    return t_client pipelined;

  function no_pipelined_func return t_client;

  function no_pipelined_func_obj return t_o_client;
END;
/

和身体:

CREATE PACKAGE BODY pkg IS
  FUNCTION pipelined_func
  RETURN t_client PIPELINED
  AS 
    v_pipe r_client;
  BEGIN 
    FOR ids IN 1..10 LOOP
        v_pipe.subs_id := ids;
        PIPE ROW(v_pipe); 
    END LOOP;
  END;

  FUNCTION no_pipelined_func
  RETURN t_client
  AS 
    l_tab  t_client;
    v_pipe r_client;
  BEGIN
    l_tab := t_client();
    FOR ids IN 1..10 LOOP
      v_pipe.subs_id := ids;
      l_tab.extend;
      l_tab(l_tab.last) := v_pipe;
    END LOOP;
    RETURN l_tab;
  END;

  FUNCTION no_pipelined_func_obj
  RETURN t_o_client
  AS 
    l_tab  t_o_client := t_o_client();
  BEGIN
    FOR ids IN 1..10 LOOP
      l_tab.extend;
      l_tab(l_tab.last) := o_client(ids);
    END LOOP;
    RETURN l_tab;
  END;
END;
/

然后:

SELECT * FROM pkg.no_pipelined_func();

失败原因:

ORA-00902: invalid datatype

但是:

SELECT * FROM pkg.pipelined_func();

SELECT * FROM pkg.no_pipelined_func_obj();

两种输出:

 类似资料:
  • 问题内容: 一个众所周知的事实是,不要停止使用Thread.stop()运行进程。 通常,手册和教程建议改用Thread.interrupt()或一些布尔变量,并从代码内部检查该中断或变量。 但是,如果我有一个库方法有时需要花费很长时间才能执行,并且我想让用户能够停止该过程?库没有给我提供执行此操作的机制(不检查线程中断状态,也没有“ stop!”变量)? 而且,更糟糕的是,要么没有库的源代码,要

  • 问题内容: 如果我使用ActionBarSherlock 3.5.1,则一切正常且正常。但是,如果我想使用4.0 RC1,则会出现错误。 有任何想法吗? 问题答案: 确保将(和您的ActionBarSherlock项目的)目标API级别设置为15。为此: 将两个AndroidManifest.xml文件中的android:targetSdkVersion都更改为“ 15”。 使用项目属性(可能也包

  • 问题内容: 我正在编写一个脚本(多线程)以从网站上检索内容,并且该网站不是很稳定,因此时不时会有一个挂起的http请求,甚至无法超时。由于我无法控制该网站,所以我唯一能做的就是改善代码,但现在我的想法已经用尽。 样例代码: 我该怎么做才能迫使挂起的请求退出?其实我想知道为什么一开始不起作用。有人可以帮我吗? 补充:(是的问题仍然没有解决) 好的,我遵循了tomasz的建议,将代码更改为,但是同样的

  • 我正在研究clojure和Scala之间的互操作。由于java本身现在有lambda,所以我想在数据和如何将函数应用到集合之间进行一个概括 Clojure函数扩展了并概括了上的集合操作 Scala函数扩展了并概括了上的集合操作 Java lambda扩展并概括了上的集合操作 问题: null Clojure、Scala和Java中都有这样的操作:获取集合、将函数应用到该集合并返回新的集合。 所有这

  • 无法调试Android应用程序。当我单击调试按钮时,应用程序会启动,但在第一个屏幕上会冻结。只有当我调试应用程序时才会发生这种情况,如果我只是运行应用程序,一切都正常。我尝试先运行应用程序,然后将调试器附加到Android进程,但没有帮助。 我不知道问题出在哪里。什么会减慢调试速度?尝试了所有这些解决方案堆栈溢出1,堆栈溢出2,intellij支持 该应用程序有相当大的代码库。如果需要,我可以提供