为什么我编写的SQL触发器中HAVING子句会报语法错误?
语法错误原因
你代码的语法错误出在HAVING子句的CASE表达式写法上:
- SQL的
CASE表达式必须以END闭合,你没有加结束标记 CASE的THEN后只能返回具体值,不能直接写count(lm.LocationID)> 0这种判断语句作为返回结果
除了语法错误外,你的代码还有逻辑漏洞:
- 你在
WHERE子句直接加了m.DELIVERYINPERSON=1的过滤条件,会导致DeliveryInPerson为0的合规供应商完全无法插入数据 - 多表用内连接的方式,如果会员没有关联支付方式/位置会直接被过滤,无法走后面的校验逻辑
GROUP BY仅写了pm.VENDORID,但SELECT里的其他非聚合字段没有加入分组,执行也会报错
修正后的完整代码
Create or alter trigger tr1 on Book_Copies instead of insert as insert into BOOK_COPIES(VENDORID, BOOKID, AVAILABLE, BOOKUSAGE, BOOKPICTURE, INSERTIONDATE) select i.VENDORID, i.BOOKID, i.AVAILABLE, i.BOOKUSAGE, i.BOOKPICTURE, getdate() from inserted i -- 关联会员表校验供应商基础属性 inner join MEMBERS m on i.VENDORID = m.MEMBERID -- 左连支付方式表,统计数量 left join PAYMENT_METHODS_MEMBERS pm on m.MEMBERID = pm.VENDORID -- 左连位置表,统计数量 left join LOCATIONS_MEMBERS lm on m.MEMBERID = lm.VENDORID where m.DELIVERYINPERSON is not null and m.EXPECTEDRESPONSETIME is not null -- 所有查询用到的非聚合字段都要加入分组 group by i.VENDORID, i.BOOKID, i.AVAILABLE, i.BOOKUSAGE, i.BOOKPICTURE, m.DELIVERYINPERSON having -- 校验至少关联一种支付方式 count(pm.PAYMENTMETHODID) > 0 -- 校验:如果DeliveryInPerson=1则至少关联一个位置 and case when m.DELIVERYINPERSON = 1 then count(lm.LocationID) else 1 end > 0 go
逻辑说明
- 用
LEFT JOIN关联支付方式、位置表,避免无关联数据时直接被过滤 CASE表达式逻辑:当DeliveryInPerson=1时返回关联的位置数量,否则返回1,只要整体结果大于0就符合要求,完美对应“仅DeliveryInPerson=1时需要校验位置”的需求;如果你需要DeliveryInPerson=1时位置数量大于1,把having子句末尾的> 0改为> 1即可- 补全了
GROUP BY的字段,符合SQL分组语法规范 - 自动把插入日期设为
getdate(),符合作业要求
内容的提问来源于stack exchange,提问作者Vasco Gameiro
相关产品推荐
相关产品推荐

