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

时间:2012-02-04 11:44:21

标签: sql database where-clause

我在应用程序的日志文件中看到了一个查询。它包含一个类似的查询:

SELECT ID FROM CUST_ATTR49 WHERE 1=0

这样的查询有什么用,必然会什么都不返回?

12 个答案:

答案 0 :(得分:58)

这样的查询可用于ping数据库。条款:

WHERE 1=0

确保发回非数据,因此无需CPU费用,无网络流量或其他资源消耗。

这样的查询可以测试:

  • 服务器可用性
  • CUST_ATTR49表存在
  • ID列存在
  • 保持联系
  • 在不更改任何行的情况下触发触发
  • 管理动态查询中的多个OR条件(例如WHERE 1=0 OR <condition>

答案 1 :(得分:12)

我能想到的一个用例:您有一个过滤器表单,您不希望有任何搜索结果。如果指定了一些过滤器,则会将它们添加到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)

答案 2 :(得分:9)

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

答案 3 :(得分:2)

引自格雷格

  

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

     

     

并将它们连接在一起。在开始时1 = 1,   最初并且有一些东西需要联系。

     

我从未见过这种用于任何注射防护的产品,就像你一样   说这似乎不会有多大帮助。我已经看到它被用作了   实施方便。 SQL查询引擎最终会忽略   1 = 1所以它应该没有性能影响。

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

答案 4 :(得分:2)

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

答案 5 :(得分:2)

作为答案-还要进一步澄清@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中将其串联在一起的字符串,或进行一些搜索/替换)。这样做将使编译器有机会优化冗余语句,并使Runtime Executer看起来更简单。

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

在上面的第二条语句中,编译器知道它甚至不必考虑条件的第二部分(cond = ?),它只会删除整个谓词。如果它是一个绑定变量,则编译器将永远无法完成。

由于您只是简单且强制地注入0/1,因此SQL注入的可能性为零。

在我的SQL中,作为一种方法,我通常将sql注入点放置为$ {literal_name},然后我什至在不使用$ {literal_name}的情况下简单地使用正则表达式搜索/替换带有适当文字的任何$ {...}事件让编译器对它进行调试。这基本上导致查询存储如下:

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

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

我要特别注意注射的药物。出于所有显而易见的原因,传递变量的主要方式是并保持绑定变量。

答案 6 :(得分:2)

这在元数据获取中非常好,并使事物通用。 许多DB具有优化器,因此它们实际上不会执行,但是它仍然是有效的SQL语句,应该在所有DB上执行。 这不会获取任何结果,但是您知道列名有效,数据类型等。如果不执行,则您知道DB出现了问题(未启动等)。 如此众多的通用程序执行此伪语句来测试和获取元数据。

答案 7 :(得分:1)

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

答案 8 :(得分:1)

在应用程序中仅需要表元数据时,此功能很有用。例如,如果您正在编写JDBC应用程序,并且想要获取表中列的列显示大小。

在此处粘贴代码段

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));
}

如果您要处理海量数据,那么使用“从表中选择*”之类的查询可能会导致性能问题,因为它会尝试从表中获取所有记录。相反,如果您提供“从表其中1 = 0 中选择*”这样的查询,则它将仅获取表元数据而不是记录,因此效率很高。

答案 9 :(得分:1)

对于每个user milso in another thread,“ WHERE 1 = 0”的另一个用途是:

  

创建表New_table_name作为选择* FROM Old_table_name WHERE 1 =   2;

     

这将创建一个具有与旧表相同模式的新表。 (非常   如果您想加载一些数据进行比较,则非常方便

答案 10 :(得分:1)

在Northwind 2007数据库中找到使用1 = 0的条件的示例。在主页上,“新客户订单”和“新采购订单”命令按钮使用“条件”设置为1 = 0的嵌入式宏。这将使用过滤器打开表单,该过滤器将强制子表单仅显示与父表单相关的记录。可以通过不使用宏打开树中的任何一种形式来验证这一点。当以这种方式打开时,所有记录均由子表单显示。

答案 11 :(得分:-3)

似乎有人试图破解你的数据库。看起来有人试过mysql注入。您可以在此处详细了解:Mysql Injection