【问题标题】:WHERE x IN (5) vs WHERE x = 5 ... why use IN?WHERE x IN (5) vs WHERE x = 5 ... 为什么使用 IN?
【发布时间】:2009-05-15 15:03:38
【问题描述】:

我最近注意到有人使用 IN 似乎有点不合适。我觉得我错过了一个技巧 - 也许有速度提升或其他什么?

这个查询:

SELECT * FROM pages WHERE is_visible IN ($visibility)

为什么要使用它?为什么不:

SELECT * FROM pages WHERE is_visible = $visibility

当然,如果是这样的话:

SELECT * FROM pages WHERE is_visible 
IN ($visibility,$invisibility,$somethingelse)

那么WHERE x IN (1,2,3) 是WHERE x = 1 OR x = 2 OR x = 3 的更好替代品,对吧?但肯定这是您应该使用 IN 的唯一场景?

无论如何,感谢您的宝贵时间 - 我期待您的回复!

【问题讨论】:

  • 感谢大家的回复。在这种情况下,$visiblity 是可信的,并且始终为 0 或 1。所以在我看来,这种使用“WHERE ... IN ...”毕竟是不必要的!
  • 现在并不总是意味着永远。开发人员可能正在为“以防万一”的时刻做准备。
  • 雅格尼。以防万一的情况永远不会到来。

标签: sql mysql syntax


【解决方案1】:

也许不知道 $visibility 是指单个值还是多个值?不太适合你的例子,但我在其他地方看到过这种用法。

【讨论】:

  • 我也看到了这个......记忆仍然困扰着我。
  • 嗯,这是一个很好的观点 - 但在这种情况下,可见性始终为 0 或 1
  • 如果 $visibility 引用多个值,这些值将如何扩展到 sql 中?如果 $visibility = '1,2,3' 这没有多大意义: SELECT * FROM pages WHERE is_visible IN ('1,2,3')
【解决方案2】:

那么WHERE x IN (1,2,3) 是WHERE x = 1 OR x = 2 OR x = 3 更好的替代品,对吧?但肯定这是您应该使用IN 的唯一场景?

不,您也可以将 IN 与子查询一起使用。

... where field in (select field from another_table)

【讨论】:

  • 这是一个很好的观点。我不认为 IN 可以与子查询一起使用
【解决方案3】:

也许 $visibility 是动态生成的,像这样:

$visibility = implode(', ', array_map('intval', array(1, 2, 3)));

其中 array(1, 2, 3) 可能来自不受信任的来源。

【讨论】:

    【解决方案4】:

    我认为了解 IN 的作用更重要。

    如果你这样做了

    SELECT * FROM pages WHERE is_visible = $visibility
    

    在上面的 $visibility 必须是一个 var 所以 is_visibile = 1,所以你的 SQL 收集所有 is_visible = 1 的地方

    在哪里

    SELECT * FROM pages WHERE is_visible IN ($visibility)
    

    $visibility 将是一组数据,如 @Ionut G. Stan 所示。

    所以你的调用看起来像 is_visible IN ('1', '2', '3')

    所以现在您的 SQL 将收集所有 1,2 和 3 行。

    希望这是有道理的。差别很大。

    【讨论】:

    • 我不明白这如何回答他的问题。他似乎很清楚 IN 的含义。
    • @Lee:根据您的评论,您给出了错误的答案:>>Kip 我认为您错了。显然他并不完全理解 IN,因为 IN 与 OR 不同。如果他做了他所说的“那么 WHERE x IN (1,2,3) 是 WHERE x = 1 OR x = 2 OR x = 3 的更好选择,对吧?”IS 实际上与 "X=1 OR X=2 OR X=3" 相同。如果说不是,在什么情况下会给出不同的查询结果呢?数据库引擎的实现可能存在差异,但从黑盒的角度来看没有区别。
    【解决方案5】:

    这里没有提高性能的技巧,但我认为也不会对性能造成任何影响。所以两种方式都可以。我同意你的观点,使用只有一个参数的 IN 子句看起来很有趣,但它仍然很容易理解。

    我认为这可能会发生,因为开发人员认为将来可能允许多个值(这样查询不会被更改)。或者可能开发人员已经习惯了可能有多个值的场景,他们只是出于习惯这样写。

    【讨论】:

    • 基普我认为你错了。显然他并不完全理解 IN,因为 IN 与 OR 不同。如果他做了他所说的“那么 WHERE x IN (1,2,3) 是 WHERE x = 1 OR x = 2 OR x = 3 的更好替代方案,对吧?”
    • 谢谢基普。我认为这个问题的所有答案都很棒,但你自己回答了这个问题:)
    • @Lee:你的评论属于你的答案,而不是这个,因为评论与这个答案无关。
    • 另一个关于样式的快速说明,使用 IN 避免了 1) 将 OR 列表括在括号中(优先顺序),并避免多次引用列名。这里最重要的是我们不知道(从上下文中) $visibility 的值是什么。绑定变量会告诉我们数据库会将其视为标量,无论它包含什么内容。
    【解决方案6】:

    In 作用于任何类型的集合操作,而 = 作用于单个值。因此,您可以将 in 用于另一个表上的多条记录,或用于表示多个值的任何其他类型的数据结构。

    【讨论】:

      【解决方案7】:

      不,这不是诡计。两种说法:

      SELECT * FROM pages WHERE is_visible IN ($visibility)
      SELECT * FROM pages WHERE is_visible = $visibility
      

      几乎相等。我们观察到这两个语句在普通情况下是等价的,例如,当$visibility 是一个值为 1 的标量时。

      但是当$visibility 包含其他内容时,这些语句不在非平凡的情况下是等效的。我们可以观察到两种形式的行为存在显着差异。考虑当$visibility 是包含这些示例值的字符串时,每个表单会发生什么:

      '1,2,3' '1 或 1=1' '从 vals v 中选择 v.val'

      我们观察到两种形式生成的 SQL 语句存在显着差异:

      SELECT * FROM pages WHERE is_visible IN (1,2,3) SELECT * FROM pages WHERE is_visible = 1,2,3 SELECT * FROM pages WHERE is_visible IN (1 OR 1=1 ) SELECT * FROM pages WHERE is_visible = 1 OR 1=1

      对于这两种形式的语句,这里的一个大问题是 SQL 注入的可能性。如果$visibility 打算作为一个标量值,那么在语句中使用绑定变量是一种更安全的方法,因为它可以避免任何人将“额外”SQL 语法滑入语句中。 (当然,使用绑定变量并不能阻止所有的 SQL 注入,但它是一种合适的方法来关闭一个漏洞。使用绑定变量也会提高可伸缩性,至少在一些 DBMS 平台上,例如 Oracle。)

      考虑当我们使用绑定变量(占位符)时会发生什么,我们知道它不会被解释为 SQL 语法。我们观察到这两个陈述ARE确实是等价的:

      SELECT * FROM pages WHERE is_visible IN (?) SELECT * FROM pages WHERE is_visible = ?

      为绑定变量提供的任何值。

      HTH

      【讨论】:

      • 你仍然有可能使用 IN 或 equals 进行 SQL 注入,这个答案与问题无关。
      • 基普,你是对的。这就是我试图指出的。最初的问题是询问他们是否“缺少某些东西”。你似乎也错过了它。这两种变体都不能防止 SQL 注入,这很容易使用绑定变量来解决。在这种情况下,即使提供了 NULL 值,这些语句也将是等效的。如果您不打算使用绑定变量,那么这些语句是显着不同的,因为它们以不同的方式易受攻击,并且我们没有得到任何关于 $visibility 包含什么的信息。我的回答是相关的。
      【解决方案8】:

      “WHERE x IN (1,2,3)”与“WHERE x = 1 OR x = 2 OR x = 3”一样。

      【讨论】:

        【解决方案9】:

        那么 WHERE x IN (1,2,3) 更好 替代 WHERE x = 1 OR x = 2 OR x = 3,对吧?但这肯定是 唯一应该使用 IN 的场景?

        IN () 和 OR 在语法上是等价的。检查您的两个建议的执行计划将显示这一点。 IN() 只是一种更有效且易于理解的符号。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-23
          • 2012-11-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多