为什么有人在SQL子句中使用WHERE 1 = 1 AND <conditions>?

为什么有人在SQL子句中使用WHERE 1=1 AND <conditions> (通过连接字符串获得SQL,或者是视图定义)

我曾经在某处看到过这将用于防止SQL注入,但这似乎很奇怪。

如果存在注射,那么WHERE 1 = 1 AND injected OR 1=1将具有WHERE 1 = 1 AND injected OR 1=1相同的结果。

稍后编辑:视图定义中的用法如何?


谢谢你的回答。

不过,我不明白为什么有人会使用这个构造来定义视图,或者在存储过程中使用它。

以此为例:

 CREATE VIEW vTest AS SELECT FROM Table WHERE 1=1 AND table.Field=Value 

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

 and <condition> 

并将它们连接在一起。 随着1=1的开始,最初and有某事联系在一起。

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

只要给Greg的回答添加一个示例代码:

 dim sqlstmt as new StringBuilder sqlstmt.add("SELECT * FROM Products") sqlstmt.add(" WHERE 1=1") ''// From now on you don't have to worry if you must ''// append AND or WHERE because you know the WHERE is there If ProductCategoryID <> 0 then sqlstmt.AppendFormat(" AND ProductCategoryID = {0}", trim(ProductCategoryID)) end if If MinimunPrice > 0 then sqlstmt.AppendFormat(" AND Price >= {0}", trim(MinimunPrice)) end if 

我已经看到它使用的条件数量可以变化。

您可以使用“AND”字符串连接条件。 然后,不要计算传入的条件数量,而是在股票SQL语句的末尾放置“WHERE 1 = 1”,并将其放在串联的条件中。

基本上,它可以节省你不得不做的条件测试,然后在他们之前添加一个“WHERE”字符串。

看起来像一个懒惰的方式,总是知道你的WHERE子句已经定义,并允许你保持添加条件,而不必检查它是否是第一个。

生成的sql代码中通常使用1 = 1表达式。 这个表达式可以简化sql生成代码,减少条件语句的数量。

实际上,我在BIRT报告中看到过这样的事情。 传递给BIRT运行时的查询的形式如下:

 select a,b,c from t where a = ? 

和'?' 在运行时被从下拉框中选择的实际参数值替换。 下拉列表中的选项由下式给出:

 select distinct a from t union all select '*' from sysibm.sysdummy1 

这样你就可以得到所有可能的值加“ * ”。 如果用户从下拉框中选择“ * ”(表示应选择a的所有值),则在运行之前必须修改查询(通过Javascript)。

由于“?” 是一个位置参数,必须保持其他的东西工作,Javascript修改查询是:

 select a,b,c from t where ((a = ?) or (1==1)) 

这基本上消除了where子句的影响,同时仍然保留位置参数。

我还看到了惰性编码器使用的AND情况,同时动态地创建了一个SQL查询。

假设你必须动态地创建一个以select * from t开始的查询并检查:

  • 名字是鲍勃; 和
  • 薪水是> $ 20,000

有些人会把第一个和第一个加在一起,然后用AND加上第一个:

 select * from t where name = 'Bob' and salary > 20000 

懒惰的程序员(这不一定是坏的特质)不能区分附加的条件,他们会从select * from t where 1=1然后在那之后加上AND子句。

 select * from t where 1=1 and name = 'Bob' and salary > 20000 

其中1 = 0,这样做是为了检查表是否存在。 不知道为什么使用1 = 1。

间接相关:当使用1 = 2时:

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

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

当我测试或重新检查数据库中的东西时,发现这种模式是有用的,所以我可以非常快速地评论其他条件:

 CREATE VIEW vTest AS SELECT FROM Table WHERE 1=1 AND Table.Field=Value AND Table.IsValid=true 

变成:

 CREATE VIEW vTest AS SELECT FROM Table WHERE 1=1 --AND Table.Field=Value --AND Table.IsValid=true 

虽然我可以看到1 = 1对于生成的SQL很有用,但我在PHP中使用的一种技术是创建一个子句数组,然后执行

 implode (" AND ", $clauses); 

从而避免了具有前导或尾随的问题。 显然这只有在你知道你将至少有一个条款时才有用!

这里有一个密切相关的例子:使用SQL MERGE语句来更新目标tabled,使用来自源表的所有值,其中没有加入的共同属性,例如

 MERGE INTO Circles USING ( SELECT pi FROM Constants ) AS SourceTable ON 1 = 1 WHEN MATCHED THEN UPDATE SET circumference = 2 * SourceTable.pi * radius; 

为什么有人会使用WHERE 1 = 1 AND <proper conditions>

我已经看到, homespun框架做这样的事情( blush ),因为这样可以将懒惰的分析实践应用于WHEREAND Sql关键字。

例如(我在这里使用C#作为示例),请考虑在Sql查询string builder中对以下谓词进行条件解析:

 var sqlQuery = "SELECT * FROM FOOS WHERE 1 = 1" if (shouldFilterForBars) { sqlQuery = sqlQuery + " AND Bars > 3"; } if (shouldFilterForBaz) { sqlQuery = sqlQuery + " AND Baz < 12"; } 

WHERE 1 = 1的“好处”意味着不需要特殊的代码:

  • 对于AND (无论是否为零),应该应用一个或两个谓词(Bars和Baz),这将决定是否需要第一个AND 。 由于我们已经至少有一个谓词,其中1 = 1 ,这意味着AND总是OK。
  • 根本没有谓词 – 在有零谓词的情况下,那么WHERE必须被删除。 但是,再次,我们可以懒惰,因为我们再次保证至少有一个谓词。

这显然是一个坏主意,并建议使用已建立的数据访问框架或ORM以这种方式解析可选谓词和条件谓词。

如果你来这里搜索WHERE 1 ,注意WHERE 1WHERE 1=1是相同的。 WHERE 1很少使用,因为有些数据库系统拒绝考虑WHERE 1不是真正的布尔值。

我第一次遇到这个ADO和经典的ASP,我得到的答案是: 性能。 如果你做一个直的

Select * from tablename

并通过作为一个SQL命令/文本,你会得到一个明显的性能提高

Where 1=1

补充说,这是一个明显的差异。 一旦遇到第一个条件就会返回一些表头信息,或者其他一些疯狂的东西,无论如何,它会加快速度。

使用1=1这样的谓词是有时用来强制访问计划使用或不使用索引扫描的常规提示。 之所以这样做,是因为在where子句中使用带有多个谓词的多嵌套联接查询,有时甚至使用所有索引都会导致访问计划读取每个表 – 全表扫描。 这只是DBA用来欺骗dbms使用更高效路径的许多提示中的一个。 只是不要扔一个; 你需要一个dba来分析查询,因为它不总是工作。

我通常在为构建具有用户可以选择的许多下拉值的报表构建动态SQL时执行此操作。 由于用户可能会或可能不会从每个下拉列表中选择值,因此我们最终难以弄清哪个条件是第一个where子句。 所以我们用where 1=1来填充查询,然后添加所有where子句。

就像是

 select column1, column2 from my table where 1=1 {name} {age}; 

然后,我们将这样构建where子句并将其作为参数值传递

 string name_whereClause= ddlName.SelectedIndex > 0 ? "AND name ='"+ ddlName.SelectedValue+ "'" : ""; 

由于'AND' or 'WHERE'.子句的选择在运行时是未知的,因此这有助于我们找出是否包含'AND' or 'WHERE'.