如何解决即使在 SQL
我有一个超过 300,000 行的存储过程,这是我第一次处理这么大的事情。 这是我正在编写的代码示例:
IF (@type = 'commande client')
AND @etat = 'ouvert'
BEGIN
IF (@tiersd = '')
AND @tiersf = ''
BEGIN
IF (@familled = '')
AND @famillef = ''
BEGIN
IF (@commerciald = '')
AND @commercialf = ''
BEGIN
IF (@articled = '')
AND @articlef = ''
BEGIN
IF (@afamilled = '')
AND @afamillef = ''
BEGIN
SELECT ordr.docentry,OITM.itemCode,rdr1.dscription,rdr1.quantity,rdr1.price,rdr1.currency,rdr1.slpCode,rdr1.basedocnum,rdr1.shiptocode,rdr1.shiptodesc,rdr1.baseprice,ordr.docnum,ordr.doctype,ordr.docstatus,ordr.docTotal,ordr.docdate,ordr.cardcode,ordr.cardname,ordr.address,ordr.doccur,ordr.paidtodate,ordr.doctime,ordr.docsubtype,ordr.basetype,ordr.baseEntry,OITM.itemclass,OITM.itemtype,OITM.itemname,OITM.itmsgrpcod
FROM ordr
INNER JOIN rdr1 ON ordr.docentry = rdr1.docentry
INNER JOIN oitm ON OITM.itemcode = rdr1.ItemCode
WHERE ordr.DocDate BETWEEN @dated AND @datef
AND DocStatus = 'o';
END;
ELSE IF (@afamilled != '')
AND @afamillef = ''
BEGIN
SELECT ordr.docentry,OITM.itmsgrpcod
FROM ordr
INNER JOIN rdr1 ON ordr.docentry = rdr1.docentry
INNER JOIN oitm ON OITM.itemcode = rdr1.ItemCode
WHERE OITM.itmsgrpcod BETWEEN @afamilled AND ((SELECT MAX(itmsgrpcod)FROM oitm))
AND ordr.DocDate BETWEEN @dated AND @datef
AND DocStatus = 'o';
END;
ELSE IF (@afamilled = '')
AND @afamillef != ''
BEGIN
SELECT ordr.docentry,OITM.itmsgrpcod
FROM ordr
INNER JOIN rdr1 ON ordr.docentry = rdr1.docentry
INNER JOIN oitm ON OITM.itemcode = rdr1.ItemCode
WHERE OITM.itmsgrpcod BETWEEN ((SELECT MIN(itmsgrpcod)FROM oitm)) AND @afamillef
AND ordr.DocDate BETWEEN @dated AND @datef
AND DocStatus = 'o';
END;
IF (@afamilled != '')
AND @afamillef != ''
BEGIN
SELECT ordr.docentry,OITM.itmsgrpcod
FROM ordr
INNER JOIN rdr1 ON ordr.docentry = rdr1.docentry
INNER JOIN oitm ON OITM.itemcode = rdr1.ItemCode
WHERE OITM.itmsgrpcod BETWEEN @afamilled AND @afamillef
AND ordr.DocDate BETWEEN @dated AND @datef
AND DocStatus = 'o';
END;
END;
----------------------------
ELSE IF (@articled != '')
AND @articlef != ''
BEGIN
IF (@afamilled = '')
AND @afamillef = ''
BEGIN
SELECT ordr.docentry,OITM.itmsgrpcod
FROM ordr
INNER JOIN rdr1 ON ordr.docentry = rdr1.docentry
INNER JOIN oitm ON OITM.itemcode = rdr1.ItemCode
WHERE OITM.itemcode BETWEEN @articled AND @articlef
AND ordr.DocDate BETWEEN @dated AND @datef
AND DocStatus = 'o';
END;
IF (@afamilled != '')
AND @afamillef = ''
BEGIN
SELECT ordr.docentry,OITM.itmsgrpcod
FROM ordr
INNER JOIN rdr1 ON ordr.docentry = rdr1.docentry
INNER JOIN oitm ON OITM.itemcode = rdr1.ItemCode
WHERE OITM.itemcode BETWEEN @articled AND @articlef
AND OITM.itmsgrpcod BETWEEN @afamilled AND ((SELECT MAX(itmsgrpcod)FROM oitm))
AND ordr.DocDate BETWEEN @dated AND @datef
AND DocStatus = 'o';
END;
IF (@afamilled = '')
AND @afamillef != ''
BEGIN
SELECT ordr.docentry,OITM.itmsgrpcod
FROM ordr
INNER JOIN rdr1 ON ordr.docentry = rdr1.docentry
INNER JOIN oitm ON OITM.itemcode = rdr1.ItemCode
WHERE OITM.itemcode BETWEEN @articled AND @articlef
AND OITM.itmsgrpcod BETWEEN ((SELECT MIN(itmsgrpcod)FROM oitm)) AND @afamillef
AND ordr.DocDate BETWEEN @dated AND @datef
AND DocStatus = 'o';
END;
IF (@afamilled != '')
AND @afamillef != ''
BEGIN
SELECT ordr.docentry,OITM.itmsgrpcod
FROM ordr
INNER JOIN rdr1 ON ordr.docentry = rdr1.docentry
INNER JOIN oitm ON OITM.itemcode = rdr1.ItemCode
WHERE OITM.itemcode BETWEEN @articled AND @articlef
AND OITM.itmsgrpcod BETWEEN @afamilled AND @afamillef
AND ordr.DocDate BETWEEN @dated AND @datef
AND DocStatus = 'o';
END;
END;
问题是,即使条件不满足,编译器似乎也会检查每个 if 语句内部,这大约需要半个小时,所以我希望找到解决此问题的方法
解决方法
是的,正如评论中提到的,SQL Server 的 T-SQL 编译器是一个真正的编译器,它试图像客户端语言编译器一样编译每一行(一些客户端语言编译器有编译器指令来解决这个问题,T -SQL 有不同的技术和特性来实现相同的目的,如下详述)。
如果您只想编译某些行,那么您将需要使用不同的方法。由于您的存储过程有 300,000 行,因此无论如何这似乎是一个非常好的主意。以下是您可能会考虑的一些技术:
- 将其分解为包含所有决策(或更高级别的决策)的主 sProc 和许多具有实际 SQL 查询(和/或较低级别的决策)的从属 sProc。
- 用于较低级别的动态 SQL。动态 SQL 在运行时被显式调用之前不会被编译(SSMS 脚本程序使用这样的技术,因此您可以查看它的示例,另一个示例是 catch-all queries)。
- 使用表驱动的代码生成自动创建正确的 SQL 代码作为预编译器阶段,实现一种或两种或前述技术。
- 使用表驱动的代码生成仅动态创建您在运行时需要的 SQL 代码,然后动态执行它。
- 上述技术的任何或所有组合。
预先警告,除第一项之外的任何内容都涉及动态 SQL,并且需要足够的 SQL 专业知识才能了解安全后果(SQL 注入等)和 how to deal with them。此外,您在此列表中越往下,您将需要越高级的技术技能和 SQL 知识来实施这些。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。