我有一个接受用户输入的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
发布于 2019-06-11 05:29:26
-302SQLCODE表示某种类型的转换错误。
可以说,DB2不会把30磅的垃圾塞进一个4磅的袋子里,它会给你一个错误。也许在转换过程中给XML一些额外的空间可能会有所帮助。如果您需要确保它最终只有4个字符,您可以显式地执行一个LEFT(XMLCAST( ... AS VARCHAR(64)), 4)
。这样,XMLCAST
就有了所需的空间,但您可以将其缩减以适应fetch上的变量。
另一件事可能是传递给参数标记的变量太长。DB2将根据ALERT_TYPE
的长度猜测类型和长度。请注意,您只能通过参数标记传递单个值。如果您传递一个逗号分隔的列表,它的行为将不会像预期的那样(除非您希望ALERT_TYPE
也包含一个逗号分隔的列表)。
发布于 2019-06-12 01:45:07
与参数一起使用的IN
谓词错误。
不要期望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
;
按原样运行该语句。然后,您可以取消对字符串with WHERE
子句的注释,并注释掉其余的子句,看看您想要做什么。
附言:
您得到的错误可能是因为您没有指定参数的数据类型(您没有使用类似于IN (cast(? as varchar(xxx)))
的数据类型,并且db2编译器假定它的长度等于ALERT_TYPE
表达式的长度(4字节)。
https://stackoverflow.com/questions/56532611
复制相似问题