如果我对数据库的一般工作方式的理解是正确的,最有效的是简单地使用WHERE ID IN(1,2,3,4,5,…)动态构建和构建查询.问题的核心是ID的输入列表将是真正的任意的,所以无论数据库如何聪明,或者我们如何巧妙地实现它,我们总是有一个随机的整数子集开始,所以最终每个方法都必须无论如何,内部归结为像WHERE ID IN(1,…)的东西.
人们可以在网络上找到许多方法.例如,一个涉及声明一个表变量,将ID的列表作为逗号分隔的字符串传递给一个存储过程,在存储过程中将其分解,将该ID插入到表变量中,并加入它的主表,这个:
-- 1. Temporary table for ID’s: DECLARE @IDS TABLE (ID int); -- 2. Split the given string of ID’s,and each ID to @IDS. -- Omitted for brevity. -- 3. Join the main table to @ID’s: SELECT MyTable.ID,MyTable.SomeColumn FROM MyTable INNER JOIN @IDS ON MyTable.ID = @IDS.ID;
将字符串操作的问题放在一边,我认为在这种情况下本质上发生的是,在第三步中,sql Server说:“谢谢,这很好,但是我只需要一个ID的列表”,它扫描表变量@IDS,然后n在MyTable中寻找,其中n是ID的编号.我做了一些基本的性能评估,并检查了查询计划,似乎这是会发生的.所以表变量,字符串连接和分割以及所有额外的INSERT都没有.
我对么?还是我缺少什么?真的有一些聪明和更有效的方式吗?基本上,我所说的是,sql Server必须做n索引,无论什么和制定查询,WHERE ID IN(1,…)是最直接的方式去问问.
解决方法
此外,这不仅仅是效率;还有安全性和正确性要担心.用户何时以及如何告诉数据库有关其ID选择?如何将它们合并到查询中?
将选定的ID放入可以加入的单独表格(或使用WHERE EXISTS对照)可能会更好.
我会给你,对于一个小的(用户生成的)n,你不太可能比IN(1,3..n)做得更好.但是,您需要考虑如何生成该查询.你要使用动态sql吗?如果是这样,你如何从注射中取得安全?服务器能否缓存执行计划?
另外,使用额外的表往往更容易.假设您正在为电子商务网站构建购物车.而不是担心跟踪购物车客户端或会话,每次用户进行选择时,最好更新ShoppingCart表.这也避免了如何安全地设置查询的参数值的整个问题,因为您一次只进行一次更改.
不要忘记旧格言(道歉Benjamin Franklin):
He who would trade correctness for performance deserves neither