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

我在某个地方看到过,这将用于防止SQL注入,但这看起来非常奇怪。

如果有一个注入WHERE 1=1和注入OR 1=1将有相同的结果注入OR 1=1。

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


谢谢你的回答。

尽管如此, 我不明白为什么有人会使用这种结构来定义视图,或者在存储过程中使用它。

举个例子:

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

当前回答

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

and <condition>

然后把它们连在一起。1=1在开头,首字母和有关联。

我从来没见过这个用于任何注射保护,就像你说的,它似乎没有多大帮助。我曾看到它被用作一种实现方便。SQL查询引擎最终会忽略1=1,因此它不会对性能产生影响。

其他回答

实际上,我在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子句的影响,同时仍然保留位置参数。

我还见过懒惰的程序员在动态创建SQL查询时使用AND大小写。

比如你必须动态创建一个以select * from t开头的查询,并检查:

我的名字叫鲍勃;而且 薪水是2万美元

有些人会在第一个单词后面加上WHERE,然后在后面的单词后面加上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

只是在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

为什么有人会使用WHERE 1=1 AND <适当条件>

我曾经见过简单的框架做这样的事情(脸红),因为这允许将惰性解析实践应用于WHERE和and Sql关键字。

例如(我在这里使用c#作为示例),考虑在Sql查询字符串构建器中对以下谓词的条件解析:

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’s),这将决定是否需要第一个AND。因为我们已经有了至少一个1 = 1的谓词,它意味着AND总是OK的。 对于根本没有谓词的情况-在有0个谓词的情况下,则必须删除where。但同样,我们可以偷懒,因为我们再次保证至少有一个谓词。

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

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

implode (" AND ", $clauses);

这样就避免了前导和后导AND的问题。显然,这只有在您知道至少有一个子句时才有用!

Using a predicate like 1=1 is a normal hint sometimes used to force the access plan to use or not use an index scan. The reason why this is used is when you are using a multi-nested joined query with many predicates in the where clause where sometimes even using all of the indexes causes the access plan to read each table - a full table scan. This is just 1 of many hints used by DBAs to trick a dbms into using a more efficient path. Just don't throw one in; you need a dba to analyze the query since it doesn't always work.