DB2 SQL错误:执行准备好的语句时,SQLCODE = -302

时间:2019-06-10 19:40:55

标签: db2 prepared-statement

我有一个接受用户输入的SQL查询,因此存在安全漏洞。

现有查询为:

SELECT  BUS_NM, STR_ADDR_1, CITY_NM, STATE_CD, POSTAL_CD, COUNTRY_CD,
        BUS_PHONE_NB,PEG_ACCOUNT_ID, GDN_ALERT_ID, GBIN, GDN_MON_REF_NB,
        ALERT_DT, ALERT_TYPE, ALERT_DESC,ALERT_PRIORITY 
FROM ( SELECT A.BUS_NM, AE.STR_ADDR_1, A.CITY_NM, A.STATE_CD, A.POSTAL_CD,
              CC.COUNTRY_CD,  A.BUS_PHONE_NB, A.PEG_ACCOUNT_ID, 'I' || 
              LPAD(INTL_ALERT_DTL_ID, 9,'0') GDN_ALERT_ID, 
              LPAD(IA.GBIN, 9,'0') GBIN, IA.GDN_MON_REF_NB,
              DATE(IAD.ALERT_TS) ALERT_DT, 
              XMLCAST(XMLQUERY('$A/alertTypeConfig/biqCode/text()' passing  
                IAC.INTL_ALERT_TYPE_CONFIG as "A") AS CHAR(4)) ALERT_TYPE, 
              , ROW_NUMBER() OVER () AS "RN" 
       FROM ACCOUNT A, Other tables 
       WHERE IA.GDN_MON_REF_NB = '100'  
         AND A.PEG_ACCOUNT_ID = IAAR.PEG_ACCOUNT_ID  
         AND CC.COUNTRY_CD = A.COUNTRY_ISO3_CD 
       ORDER BY IA.INTL_ALERT_ID ASC )  
WHERE  ALERT_TYPE  IN (" +TriggerType+ ");

我将其更改为从setString接受TriggerType,例如:

SELECT BUS_NM, STR_ADDR_1, CITY_NM, STATE_CD, POSTAL_CD, COUNTRY_CD,
       BUS_PHONE_NB,PEG_ACCOUNT_ID, GDN_ALERT_ID, GBIN, GDN_MON_REF_NB,
       ALERT_DT, ALERT_TYPE, ALERT_DESC,ALERT_PRIORITY 
FROM ( SELECT A.BUS_NM, AE.STR_ADDR_1, A.CITY_NM, A.STATE_CD, A.POSTAL_CD, 
              CC.COUNTRY_CD,  A.BUS_PHONE_NB, A.PEG_ACCOUNT_ID, 
              'I' || LPAD(INTL_ALERT_DTL_ID, 9,'0') GDN_ALERT_ID,
              LPAD(IA.GBIN, 9,'0') GBIN, IA.GDN_MON_REF_NB, 
              DATE(IAD.ALERT_TS) ALERT_DT, 
              XMLCAST(XMLQUERY('$A/alertTypeConfig/biqCode/text()' passing  
                IAC.INTL_ALERT_TYPE_CONFIG as "A") AS CHAR(4)) ALERT_TYPE, 
              ROW_NUMBER() OVER () AS "RN" 
       FROM ACCOUNT A, other tables 
       WHERE IA.GDN_MON_REF_NB = '100'  
         AND A.PEG_ACCOUNT_ID = IAAR.PEG_ACCOUNT_ID   
         AND CC.COUNTRY_CD = A.COUNTRY_ISO3_CD 
       ORDER BY IA.INTL_ALERT_ID ASC )  
WHERE  ALERT_TYPE  IN (?);

设置触发类型如下:

if (StringUtils.isNotBlank(request.getTriggerType())) {
   preparedStatement.setString(1, triggerType != null ? triggerType.toString() : "");
}

获取错误

  

由以下原因引起:com.ibm.db2.jcc.am.SqlDataException:DB2 SQL错误:SQLCODE = -302,SQLSTATE = 22001,SQLERRMC = null,DRIVER = 4.19.26

2 个答案:

答案 0 :(得分:0)

-302 SQLCODE表示某种转换错误。

SQLSTATE 22001通过告诉我们您正在尝试将大字符串强制为小变量来缩小范围。鉴于您的问题信息有限,我猜想是XMLCAST才是罪魁祸首。

DB2不会将30磅的废纸jam塞到4磅的袋子中,可以这么说,这会给您带来错误。也许在转换中给XML一些额外的空间可能会有所帮助。如果需要确保它最终只有4个字符长,则可以显式执行LEFT(XMLCAST( ... AS VARCHAR(64)), 4)。这样,XMLCAST便拥有了所需的空间,但是您将其切回以适合您的变量,以适应​​提取。

另一件事可能是传递给参数标记的变量太长。 DB2将根据ALERT_TYPE的长度猜测类型和长度。请注意,您只能通过参数标记传递单个值。如果传递逗号分隔的列表,它将不会按预期方式工作(除非您期望ALERT_TYPE也包含逗号分隔的列表)。如果要从表中获取逗号分隔的列表,则可以使用子选择。

答案 1 :(得分:0)

IN ('AAAA, M250, ABCD')谓词与参数一起使用错误。
不要指望IN ('AAAA', 'M250', 'ABCD')(在您尝试通过逗号分隔的字符串作为单个参数传递时)会像select t.* from ( select XMLCAST(XMLQUERY('$A/alertTypeConfig/biqCode/text()' passing IAC.INTL_ALERT_TYPE_CONFIG as "A") AS CHAR(4)) ALERT_TYPE from table(values xmlparse(document '<alertTypeConfig><biqCode>M250, really big code</biqCode></alertTypeConfig>')) IAC(INTL_ALERT_TYPE_CONFIG) ) t --WHERE ALERT_TYPE IN ('AAAA, M250, ABCD') join xmltable('for $id in tokenize($s, ",\s?") return <i>{string($id)}</i>' passing cast('AAA, M250 , ABCD' as varchar(200)) as "s" columns token varchar(200) path '.') x on x.token=t.ALERT_TYPE ; (根据需要)那样工作。这些谓词不相等。
如果要传递如下这样的逗号分隔的字符串,则需要一些“字符串标记器”。

WHERE

按原样运行该语句。然后,您可以使用IN (cast(? as varchar(xxx)))子句取消注释该字符串,并注释掉其余部分以查看您尝试执行的操作。

P.S .:
您得到的错误可能是因为您未指定参数的数据类型(您未使用诸如ALERT_TYPE之类的信息,并且db2编译器假定其长度等于{{1}的长度)。 }表达式(4个字节)。