为啥要在 SQL 中使用 WHERE 1=0 语句?

Posted

技术标签:

【中文标题】为啥要在 SQL 中使用 WHERE 1=0 语句?【英文标题】:why would you use WHERE 1=0 statement in SQL?为什么要在 SQL 中使用 WHERE 1=0 语句? 【发布时间】:2012-02-26 18:38:18 【问题描述】:

我看到一个查询在应用程序的日志文件中运行。它包含如下查询:

SELECT ID FROM CUST_ATTR49 WHERE 1=0

这样一个注定什么都不返回的查询有什么用?

【问题讨论】:

这很可能是解决某些 ORM“功能”的黑客。 你在哪里找到这样的查询? 复制:***.com/questions/517107/… 就 ORM 而言,这个没有使用 TOPLink 或 Hibernate 之类的东西。我听说它有自己的实现 @Krumelur:我不会说这是重复的,WHERE 1 = 1 返回表中的所有行,WHERE 1 = 0 没有返回,这意味着它们可以以不同的方式使用,如最佳答案中所述 【参考方案1】:

在ActiveRecord ORM 中,RubyOnRails 的一部分:

Post.where(category_id: []).to_sql

# => SELECT * FROM posts WHERE 1=0

这大概是因为以下是无效的(至少在 Postgres 中):

select id FROM bookings WHERE office_id IN ()

【讨论】:

【参考方案2】:

这样的查询可用于 ping 数据库。子句:

WHERE 1=0

确保发回非数据,因此不会产生 CPU 费用、网络流量或其他资源消耗。

这样的查询可以测试:

服务器可用性 CUST_ATTR49 表存在 ID 列存在 保持连接有效 在不更改任何行的情况下触发触发器(使用 where 子句,但不在选择查询中) 管理动态查询中的许多 OR 条件(例如 WHERE 1=0 OR <condition>

【讨论】:

另一种可能的用途:如果您的桌子上有触发器,例如DELETE 你可以做DELETE FROM [Table] WHERE 1 = 0 这将导致触发器在不更改任何行的情况下触发。例如,如果您的触发器更新其他表并且您希望确保所有内容都是最新的等,则很有用。 @AndreaColleoni 您应该在我们可以在进行动态查询时添加 1=0 的地方添加很多 or 条件【参考方案3】:

在 Northwind 2007 数据库中找到了使用 1=0 的 where 条件的示例。在主页上,New Customer Order 和 New Purchase Order 命令按钮使用嵌入的宏,其中 Where Condition 设置为 1=0。这将打开带有过滤器的表单,该过滤器强制子表单仅显示与父表单相关的记录。这可以通过在不使用宏的情况下从树中打开其中任何一种形式来验证。以这种方式打开时,所有记录都由子表单显示。

【讨论】:

【参考方案4】:

作为一个答案 - 同时也是对@AndreaColleoni 已经提到的内容的进一步澄清:

管理动态查询中的许多 OR 条件(例如 WHERE 1=0 OR <condition>

用作开/关开关

我将其用作部分查询的开关(开/关)语句。

如果我要使用

WHERE 1=1
  AND (0=? OR first_name = ?) 
  AND (0=? OR last_name = ?)

然后我可以使用第一个绑定变量 (?) 来打开或关闭 first_name 搜索条件。 ,以及第三个绑定变量 (?) 来打开或关闭 last_name 标准。

我还添加了一个文字 1=1 只是为了美观,因此查询的文本可以很好地对齐。

对于这两个标准,它似乎没有多大帮助,因为通过仅放置 first_namelast_name 或两者,或两者来动态构建您的 WHERE 条件,可能会更容易做到这一点没有。因此,您的代码必须动态构建同一查询的 4 个版本。想象一下,如果您要考虑 10 个不同的条件会发生什么,那么您需要管理多少个相同查询的组合?

编译时间优化

我还可以添加 0=?如果您的所有条件都被索引,则绑定变量开关将无法很好地工作。将选择适当索引和执行计划的运行时优化器可能只是看不到在那些稍微复杂的谓词中使用索引的成本效益。因此,我通常建议将 0 / 1 显式注入到您的查询中(将其连接到您的 sql 中的字符串,或进行一些搜索/替换)。这样做将使编译器有机会优化冗余语句,并为运行时执行器提供更简单的查询。

(0=1 OR cond = ?) --> (cond = ?)
(0=0 OR cond = ?) --> Always True (ignore predicate)

在上面的第二条语句中,编译器知道它甚至不需要考虑条件的第二部分 (cond = ?),它会简单地删除整个谓词。如果它是一个绑定变量,编译器永远不可能做到这一点。

因为您是简单且强制地注入 0/1,所以 SQL 注入的可能性为零。

在我的 SQL 中,作为一种方法,我通常将我的 sql 注入点放置为 $literal_name,然后在我什至之前使用正则表达式使用适当的文字搜索/替换任何出现的 $...让编译器尝试一下。这基本上导致查询存储如下:

WHERE 1=1
  AND (0=$cond1_enabled OR cond1 = ?)
  AND (0=$cond2_enabled OR cond2 = ?)

看起来不错,易于理解,编译器可以很好地处理它,并且基于运行时成本的优化器可以更好地理解它,并且更有可能选择正确的索引。

我对注射的东西特别小心。出于所有显而易见的原因,传递变量的主要方式是并且仍然是绑定变量。

【讨论】:

【参考方案5】:

这在元数据获取方面非常好,并使事情变得通用。 许多数据库都有优化器,因此它们实际上不会执行它,但它仍然是有效的 SQL 语句,应该在所有数据库上执行。 这不会获取任何结果,但您知道列名是有效的、数据类型等。如果它不执行,您知道 DB 有问题(未启动等) 如此多的通用程序执行这个虚拟语句来测试和获取元数据。

【讨论】:

【参考方案6】:

根据user milso in another thread,“WHERE 1=0”的另一个用途:

CREATE TABLE New_table_name as select * FROM Old_table_name WHERE 1 = 2;

这将创建一个与旧表具有相同架构的新表。 (非常 如果你想加载一些数据进行比较,这很方便)

【讨论】:

【参考方案7】:

当应用程序中只需要表元数据时,它会很有用。例如,如果您正在编写一个 JDBC 应用程序,并且想要获取表中列的列显示大小。

在此处粘贴代码 sn-p

String query = "SELECT * from <Table_name> where 1=0";
PreparedStatement stmt = connection.prepareStatement(query);
ResultSet rs = stmt.executeQuery();
ResultSetMetaData rsMD  = rs.getMetaData();
int columnCount = rsMD.getColumnCount();
for(int i=0;i<columnCount;i++) 
    System.out.println("Column display size is: " + rsMD.getColumnDisplaySize(i+1));

如果您正在处理大量数据,这里有一个像“select * from table”这样的查询可能会导致性能问题,因为它会尝试从表中获取所有记录。相反,如果您提供像“select * from table where 1=0”这样的查询,那么它将只获取表元数据而不是记录,因此它会很有效。

【讨论】:

【参考方案8】:

如果用户只打算追加记录,那么最快的方法是打开记录集而不返回任何现有记录。

【讨论】:

【参考方案9】:

一些系统使用脚本并且可以动态地将选定的记录设置为从完整列表中隐藏;因此需要将错误条件传递给 SQL。例如,出于医疗原因,500 条记录中的 3 条可能被标记为隐私,并且不应对所有人可见。动态查询将控制 500 条记录对 HR 人员可见,而 497 条记录对经理可见。一个值将传递给有条件设置的 SQL 子句,即“WHERE 1=1”或“WHERE 1=0”,具体取决于登录系统的用户。

【讨论】:

【参考方案10】:

这也可用于从表中提取表模式,而不提取该表中的任何数据。正如 Andrea Colleoni 所说,这些将是使用它的其他好处。

【讨论】:

【参考方案11】:

我能想到的一个用例:您有一个过滤器表单,您不想在其中看到任何搜索结果。如果你指定了一些过滤器,它们会被添加到 where 子句中。

或者,如果您必须手动创建 sql 查询,通常会使用它。例如。您不想检查 where 子句是否为空..您可以添加如下内容:

where := "WHERE 0=1"

if X then where := where + " OR ... "
if Y then where := where + " OR ... "

(如果用 OR 连接子句,则需要 0=1,如果使用 AND,则需要 1=1)

【讨论】:

究竟如何?你能举个例子吗?【参考方案12】:

引自格雷格

如果条件列表在编译时未知,而是 在运行时构建,您不必担心是否有一个 或多个条件。你可以像这样生成它们:

并将它们连接在一起。开始时 1=1, 初始并且有一些关联。

我从来没有见过它用于任何类型的注射保护,因为你 说它似乎没有多大帮助。我已经看到它用作 实施方便。 SQL 查询引擎最终会忽略 1=1 所以它应该不会影响性能。

Why would someone use WHERE 1=1 AND <conditions> in a SQL clause?

【讨论】:

我读到了,但我认为 OR 会在 1=0 的情况下使用,直到我得到这个问题的答案【参考方案13】:

似乎有人试图破解您的数据库。看起来有人尝试过mysql注入。你可以在这里阅读更多信息:Mysql Injection

【讨论】:

首先叫SQL注入,不是mysql注入。其次,这是一种常用的做法,它本身并没有透露任何恶意意图,并且与 SQL 注入没有直接关系,尽管我通常会注入 1 = 0 以提高查询计划性能。

以上是关于为啥要在 SQL 中使用 WHERE 1=0 语句?的主要内容,如果未能解决你的问题,请参考以下文章

sql查询语句的各个命令执行的标准顺序是啥?为啥?

为啥不能再where语句中直接使用聚合函数

sql查询语句的各个命令执行的标准顺序是啥?为啥?

Sql where 子句

为啥sql查询语句中的count(*)等聚合函数可以放在having后面,而不能放在where后面?

SQL查询语句中,为啥在WHERE后面查询条件有的要加单引号,有的不用加,啥时候加,啥时候不加?