【问题标题】:java.sql.SQLException: Invalid column type when executing procedure with package level types from jdbcjava.sql.SQLException:使用来自 jdbc 的包级别类型执行过程时,列类型无效
【发布时间】:2018-01-25 22:06:07
【问题描述】:

问题描述: 我正在尝试通过 java 代码调用存储在我的数据库中的过程。我要调用的过程有一个类型为“MAP_VARCHAR”的参数(我已将其定义为以下包中的类型)。

现在,我正在尝试从我的 java 代码中执行此过程,但是传递参数会给出 java.sql.SQLException。

SQL 包向您展示我是如何创建我的 SQL 过程和类型的

--------------------------------------------------------
--   Package Body TEST_PACKAGET
--------------------------------------------------------

  CREATE OR REPLACE EDITIONABLE PACKAGE BODY "TEST_PACKAGE" AS

  PROCEDURE PerformersRole(P_Performer_Map MAP_VARCHAR) AS
  BEGIN

        DBMS_OUTPUT.PUT_LINE('Hello ' || P_Performer_Map('Engineer'));

  END PerformersRole;

END TEST_PACKAGE;

/
--------------------------------------------------------
--   Package TEST_PACKAGE
--------------------------------------------------------

  CREATE OR REPLACE EDITIONABLE PACKAGE "TEST_PACKAGE" AS 

  /* TODO enter package declarations (types, exceptions, methods etc) here */ 
  TYPE MAP_VARCHAR IS TABLE OF VARCHAR(100) INDEX BY VARCHAR(100);

  PROCEDURE PerformersRole(P_Performer_Map MAP_VARCHAR);
END TEST_PACKAGE;

/

我的 java 代码

    public void executeProcedure(){

       CallableStatement statement = null;
        try {

/// Oracle Connection code should be here 
             Connection connection = connectionManager.createConnection();


            Hashtable newMap = new Hashtable();

            newMap.put("Engineer", "Hanson");
            newMap.put("Assistant", "Alice Kim");
            newMap.put("Supervisor", "James MaCoy");


            StringBuffer procedure = new StringBuffer("{call TEST_PACKAGE.PerformersRole(?) }");
            statement = connection.prepareCall(procedure.toString());
            statement.setInt(1, newMap );

            statement.execute();
        } catch (Exception ex) {


        } 

} 

我在执行 java 代码时收到的错误是

java.sql.SQLException: Invalid column type
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:8761)
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8259)
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:9012)
    at oracle.jdbc.driver.OracleCallableStatement.setObject(OracleCallableStatement.java:4983)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:230)

我错过了什么?!

提前感谢您的帮助

【问题讨论】:

  • 您的程序似乎不接受整数作为输入值,一定有比setInt 更相关的方法。
  • 什么是 MAP_VARCHAR 类型?
  • MAP_VARCHAR 是自定义类型,它将保存 VARCHAR 表并由 VARCHAR 索引。即 item('Madrid'):= 'Real Madrid'

标签: java sql oracle procedure


【解决方案1】:

在 Oracle 11.2 中,无法使用 jdbc 中的包级别类型。并且不可能在 sql 级别上创建关联数组。

此代码将失败。

create  TYPE MAP_VARCHAR IS TABLE OF VARCHAR(100) INDEX BY VARCHAR(100);

一个例外是 varchar 的关联数组或 binary_integer 的数字索引。 Accessing PL/SQL Associative Arrays

【讨论】:

  • 感谢您的有用评论@ArkadiuszŁukasiewicz 我希望我能投票给它有用,但我刚刚创建了我的帐户,我不能投票,因为我的声誉是
【解决方案2】:

好的,在 Arkadiusz Łukasiewicz 发表评论后,我花了一些时间试图弄清楚如何克服这个问题,由于他没有提供任何官方文件提及这一点,我做了快速研究,似乎他的说法是合法的。

有两种方法可以解决从您的 java 访问 SQL 包级别类型的问题:

方法#1
Panser 在以下 URL 中提供的答案
[https://stackoverflow.com/a/25989632/8477836][1]

您所需要的只是构建 SQL DECLARE ... BEGIN ... END 块,然后从您的 java.lang.

方法#2
我在单独的表中插入了我想在我的过程中传递的级别类型(MAP_VARCHAR)值,然后在我的 SQL 包中,我创建了函数来使用我创建的表中的游标检索这些值并将返回的值存储到我的本地变量中类型为 (MAP_VARCHAR)

负责存储 MAP_VARCHAR 值的函数

    FUNCTION GET_MAP_VARCHAR(P_PROCESS_ID NUMBER)
    RETURN MAP_VARCHAR IS
      LV_MAP_VARCHAR MAP_VARCHAR;
      LV_MAP_VARCHAR_TABLE_ROW EPAD_WF_RESD_PRFM_RLE%ROWTYPE;

        CURSOR C_GET_MAP_VARCHAR_ROWIS 
            SELECT * FROM TEST T
            WHERE T.TEST = P_PROCESS_ID;

  BEGIN

      FOR R_GET_MAP_VARCHAR_ROWIN C_GET_MAP_VARCHAR_ROWLOOP
        LV_MAP_VARCHAR(R_GET_MAP_VARCHAR_ROW .ROLE):= R_GET_MAP_VARCHAR_ROW.NAME;
      END LOOP;

    RETURN LV_MAP_VARCHAR;

  END GET_MAP_VARCHAR

我的新 SQL 过程应如下所示:

  CREATE OR REPLACE EDITIONABLE PACKAGE BODY "TEST_PACKAGE" AS

  PROCEDURE PerformersRole(P_ID Number) AS

    LV_Performer_Map MAP_VARCHAR
  BEGIN
    LV_Performer_Map MAP_VARCHAR= GET_MAP_VARCHAR(P_PROCESS_ID NUMBER);

        DBMS_OUTPUT.PUT_LINE('Hello ' || LV_Performer_Map('Engineer'));

  END PerformersRole;

希望这将帮助任何在从 Java 访问 SQL 包类型时遇到问题的人

【讨论】:

    【解决方案3】:

    除了所有其他答案之外,我们遇到问题的情况有所不同。此错误不是您可以诊断的“确切”错误,但您必须假设它所抱怨的列是问题的线索。

    我们在其中一个数据库上遇到了同样的问题,问题是查询有一个子查询,该查询需要一个项目,但被传递了一个数据数组。这引发了主查询,因此它报告了具有数据数组的列的“无效列”。检查以确保您的主查询未使用子查询或子查询。如果它正在使用子查询,请检查它们中的每一个,并确保它们都按照您的期望返回。

    【讨论】:

      猜你喜欢
      • 2018-07-28
      • 1970-01-01
      • 1970-01-01
      • 2013-01-26
      • 2012-03-21
      • 1970-01-01
      • 2016-10-24
      • 1970-01-01
      • 2015-03-19
      相关资源
      最近更新 更多