【发布时间】:2016-06-04 05:51:45
【问题描述】:
我需要编写一个 MySQL 存储过程(从 .NET 调用),它搜索 stoppoints 的表并允许我指定一些可能的 stopMode 值来匹配。
换句话说:
CREATE PROCEDURE getActiveStoppoints(
IN NamePrefix VARCHAR(100),
IN StopModeMatch1 TINYINT(4),
IN StopModeMatch2 TINYINT(4),
IN StopModeMatch3 TINYINT(4),
IN StopModeMatch4 TINYINT(4),
IN StopModeMatch5 TINYINT(4)
)
BEGIN
-- Return all records matching
SELECT sp.* FROM stoppoints sp
WHERE (sp.name LIKE CONCAT(NamePrefix, '%')
AND
(
(sp.stopMode = StopModeMatch1) OR
(sp.stopMode = StopModeMatch2) OR
(sp.stopMode = StopModeMatch3) OR
(sp.stopMode = StopModeMatch4) OR
(sp.stopMode = StopModeMatch5)
)
;
END
这种方法看起来非常脆弱——例如,如果我需要传入 6 个可能的 stopMode 值,甚至是 600,该怎么办?当我想以类似方式匹配另外两列时会发生什么?
还有哪些其他可能的方法来实现这一目标?例如,我可以将数组传递给存储过程吗?
我最初通过在VARCHAR 中传递一个逗号分隔的值列表来尝试这个。我最终对这种方法感到非常沮丧,因为:
- 使用
FIND_IN_SET匹配逗号分隔的字符串不使用任何索引,因此性能很差,因此不是有效的解决方案。 - 使用
PREPARE、EXECUTE、CONCAT等创建准备好的 SQL 语句感觉很脆弱,而且性能也不是很好。首先,如果与字符串匹配,我需要处理在值周围加上引号。而且我还假设每次运行存储过程时都必须重新创建查询计划? - 尝试将 CSV 值拆分到一个临时表中,然后使用子选择 确实 工作,但感觉很 hacky。另外,当您尝试将其分离到存储过程中时,您无法从存储过程中返回表/行;相反,您必须记住临时表名并首先调用存储的过程。它不会超出仅在一列中的使用范围。
当我说我花了几个小时研究这个问题无济于事时,请相信我。如何在 MySQL 中实现这一点,或者它根本不是为这种存储过程设计的?
【问题讨论】:
-
可能的相关问题:Parameterize an SQL IN clause ;).