Java:在DB2 SQL查询中将数组设置为参数名时出现问题

fgw7neuy  于 2022-11-07  发布在  DB2
关注(0)|答案(2)|浏览(238)

DB2驱动程序版本:4.19.66
DB2安装版本: db2 版本11.5.7.0
Java版本:1.8_121型

我正在尝试设置DB2 SQL查询的参数:

SELECT distinct object_id AS oid 
FROM myschema.package p 
INNER JOIN myschema.package_item pi ON p.machine_id = pi.machine_id 
                                    AND p.package_id = pi.package_id 
INNER JOIN main_schema.item i ON i.item_id = pi.id_articulo
WHERE p.package_status_id = 5 AND p.machine_id IN (:machineIdsParam)

我必须指出,p.machine_id是DB2数据库中一个INTEGER字段。
我这样准备连接:

Properties properties = new Properties();         // Create Properties object
properties.put("user", config.getDbUser());       // Set user ID for connection
properties.put("password", bdPassword);           // Set password for connection
properties.put("enableNamedParameterMarkers", 1);
connection = (DB2Connection) DriverManager.getConnection(config.getDbUrl(), properties);

然后,我尝试设置此查询的参数:

DB2PreparedStatement ps = connection.getPreparedStatement(sqlString);
List<Integer> machineIds = Array.asList(new Integer[] { 1, 5, 7, 9});
Array machineIdArray = connection.createArrayOf("INTEGER", machineIds.toArray(new Integer[idInstalaciones.length]));
ps.setJccArrayAtName("machineIdsParam", machineIdArray);

但我得到这个错误:

com.ibm.db2.jcc.am.SqlSyntaxErrorException: [jcc][1091][10417][4.19.66] Invalid data conversion: Parameter instance com.ibm.db2.jcc.am.o@36fc695d is invalid for the requested conversion.

我找不到如何使用这个setJccArrayAtName()的例子,只有文档,我无法找到这个错误的原因。我只是猜测它与数据类型有关,但我不知道如何使它工作。

u7up0aaq

u7up0aaq1#

对于LUW的Db2:

... IN 
(
  SELECT TOK
  FROM XMLTABLE
  (
    'for $id in tokenize($s, ",") return <i>{string($id)}</i>' 
    PASSING CAST (:machineIdsParam AS VARCHAR (100)) AS "s"
    COLUMNS
      TOK INT PATH '.'
  )
)

:machineIdsParam参数传递一个字符串,如'1,2,3'。即:以逗号分隔int值

mitkmikd

mitkmikd2#

我不相信任何Db2系列都支持带有IN predicate 的数组。
通常需要单独的参数

SELECT distinct object_id AS oid 
FROM myschema.package p 
INNER JOIN myschema.package_item pi ON p.machine_id = pi.machine_id 
                                    AND p.package_id = pi.package_id 
INNER JOIN main_schema.item i ON i.item_id = pi.id_articulo
WHERE p.package_status_id = 5 AND p.machine_id IN (:machineId1 
                                                   ,:machineId2
                                                   ,:machineId3
                                                   ,:machineId4
                                                  )

当然,这要求您事先知道需要多少个值,或者至少是某个最大值。(您始终可以加载任何剩余参数中的最后一个值。)
另一种选择是传递一个分隔字符串,将其拆分为单独的值。

SELECT distinct object_id AS oid 
FROM myschema.package p 
INNER JOIN myschema.package_item pi ON p.machine_id = pi.machine_id 
                                    AND p.package_id = pi.package_id 
INNER JOIN main_schema.item i ON i.item_id = pi.id_articulo
WHERE p.package_status_id = 5 AND p.machine_id IN (select int(element)
                                                   from table (systools.split(:machineIds, ' '))
                                                  )

systools.split()可能是特定于IBM i的Db2的,其他平台可能在不同的模式中具有它。
如果没有其他方法,您可以编写自己的用户定义函数(UDF)来执行拆分。

相关问题