注册
聊聊SQL查询语句中IN语句的一些坑
专栏/写意人生/ 文章详情 /

聊聊SQL查询语句中IN语句的一些坑

写意人生 2022/03/30 1933 3 0
摘要 聊聊SQL查询语句中IN语句的一些坑

在实际项目支持过程中,碰到一些执行效率很慢的SQL语句。
下面以一个SQL语句的IN语句为例,和大家分享一下IN语句可能存在的坑。具体完整的SQL查询语句如下:
1、SQL查询语句
SELECT
COUNT(1)
FROM
(
SELECT
ID
FROM
HN_WORKFLOW_ZFW_XN_TEST.WF_NODE
WHERE
FLOWID IN
(
SELECT
ID
|| ‘
|| MAX( VER )
FROM
HN_WORKFLOW_ZFW_XN_TEST.WF_FLOW
WHERE
FLOWSTATUS=‘2’
AND USABLE=‘1’
AND ISDELETE=0
GROUP BY
ID
)
AND NODEWORKTYPE!=4
)
T;
查询可以正常出结果,语句的执行效率一般。
其中涉及到的IN语句如下所示,红色部分是限制条件。
image.png
通过分析后发现,ISDELETE=0这个限定条件中的ISDELETE字段在WF_FLOW表中是不存在的,这个字段存在于WF_NODE表中。但是查询语句没有报错,而且可以正常出结果。为了进一步分析,下面把WF_FLOW和WF_NODE表的结构列出来。
2、查询语句中WF_NODE和WF_FLOW表的结构
(1)WF_NODE表
CREATE TABLE “HN_WORKFLOW_ZFW_XN_TEST”.“WF_NODE”
(
“ID” VARCHAR(100) NOT NULL,
“NODECODE” VARCHAR(100),
“STEP” NUMBER(11,0) DEFAULT 0,
“FLOWID” VARCHAR(300),
“NAME” VARCHAR(400),
“NODEFRMID” VARCHAR(100) DEFAULT ‘’,
“DELIVERYWAY” NUMBER(11,0) DEFAULT 0,
“TODOLISTMODEL” NUMBER(11,0) DEFAULT 0,
“HISTONDS” CLOB,
“X” NUMBER(11,0) DEFAULT 0,
“Y” NUMBER(11,0) DEFAULT 0,
“ICON” VARCHAR(140) DEFAULT ‘’,
“NODEWORKTYPE” NUMBER(11,0) DEFAULT 0,
“FLOWNAME” VARCHAR(400) DEFAULT ‘’,
“NODEPOSTYPE” NUMBER(11,0) DEFAULT 0,
“ORGSCOPE” NUMBER(11,0),
“ROLEIDS” VARCHAR(512),
“CREATETIME” TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP,
“UPDATETIME” TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP,
“ISDELETE” NUMBER(11,0) DEFAULT 0 NOT NULL,
“URL” VARCHAR(1000),
“ISAUTO” NUMBER(11,0) DEFAULT 0 NOT NULL,
CONSTRAINT “SYS_C00104488” NOT CLUSTER PRIMARY KEY(“ID”)) ;
CREATE INDEX “IDX_NODEWORKTYPE” ON “HN_WORKFLOW_ZFW_XN_TEST”.“WF_NODE”(“NODEWORKTYPE” ASC) ;
CREATE INDEX “IDX_FLOWID” ON “HN_WORKFLOW_ZFW_XN_TEST”.“WF_NODE”(“FLOWID” ASC) ;
(2)WF_FLOW表结构
CREATE TABLE “HN_WORKFLOW_ZFW_XN_TEST”.“WF_FLOW”
(
“ID” VARCHAR(400) DEFAULT ‘’ NOT NULL,
“FLOWCODE” VARCHAR(400) DEFAULT ‘’ NOT NULL,
“FLOWSORT” VARCHAR(200),
“NAME” VARCHAR(1000),
“FLOWORDER” NUMBER(11,0),
“FLOWICON” VARCHAR(100),
“FLOWMARK” VARCHAR(300),
“FLOWSTATUS” NUMBER(11,0),
“FLOWEDITOR” VARCHAR(200),
“FLOWDES” VARCHAR(1000),
“VER” VARCHAR(40) DEFAULT ‘’ NOT NULL,
“USABLE” NUMBER(11,0),
“CREATETIME” TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP,
“CREATEUSER” VARCHAR(100),
“UPDATEUSER” VARCHAR(100),
“UPDATETIME” TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP,
“PUBLISHUSER” VARCHAR(100),
“PUBLISHTIME” TIMESTAMP(6),
CONSTRAINT “SYS_C00104481” NOT CLUSTER PRIMARY KEY(“ID”, “VER”)) ;
CREATE INDEX “IDX_FLOWSTATUS” ON “HN_WORKFLOW_ZFW_XN_TEST”.“WF_FLOW”(“FLOWSTATUS” ASC) ;
CREATE INDEX “IDX_USABLE” ON “HN_WORKFLOW_ZFW_XN_TEST”.“WF_FLOW”(“USABLE” ASC) ;
CREATE INDEX “IDX_ID” ON “HN_WORKFLOW_ZFW_XN_TEST”.“WF_FLOW”(“ID” ASC) ;
通过对查询语句和两张表的结构分析发现,ISDELETE字段存在于WF_NODE表中,开发人员为什么把这个限定条件写在WF_FLOW表查询中,原因我们不得而知。再深入分析会发现,如果在IN语句的限定条件中在加入其他不存在的限制条件,查询语句依然可以正常执行并出结果。
请看下面示例:
把WF_NODE表中的ORGSCOPE限定条件加入到查询语句中,查询语句可以正常执行,没有报错信息。
SELECT
COUNT( 1 )
FROM
(
SELECT
ID
FROM
HN_WORKFLOW_ZFW_XN_TEST.WF_NODE
WHERE
FLOWID IN
(
SELECT
ID
|| '

|| MAX( VER )
FROM
HN_WORKFLOW_ZFW_XN_TEST.WF_FLOW
WHERE
FLOWSTATUS=‘2’
AND USABLE=‘1’
AND ISDELETE=0
AND ORGSCOPE=1
GROUP BY
ID
)
AND NODEWORKTYPE!=4
)
T;
通过测试发现,在IN语句中,对where的限定条件没有严格限制。一些不存在的限定条件被放在查询语句中,语句可以正常执行,但会影响查询的结果和SQL语句执行计划。所以对于这些问题,以下建议可供参考。
(1)对IN语句中WHERE的限定条件进行检查,不存在的限定条件不要写在语句中。
(2)推荐使用EXISTS改写IN语句。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服