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

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

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

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

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


谢谢你的回答。

< p >, 我不明白为什么有人会使用这种结构来定义视图,或者在存储过程中使用它

举个例子:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value
254224 次浏览

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

and <condition>

然后把它们连在一起。有了1=1作为开始,初始的and就有了关联。

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

似乎是一种懒惰的方式,总是知道WHERE子句已经定义,并允许您继续添加条件,而不必检查它是否是第一个条件。

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

我曾见过在条件数量可变的情况下使用这种方法。

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

基本上,它使您不必对条件进行测试,然后在它们之前添加“WHERE”字符串。

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

实际上,我在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

我第一次用ADO和经典asp遇到这个问题,我得到的答案是:<强大的>性能。 如果你直接做

Select * from tablename

并将其作为SQL命令/文本传入,您将获得显著的性能提升

Where 1=1

另外,这是一个明显的差异。只要满足第一个条件,就会返回表头,或者其他一些疯狂的事情,总之,它确实加快了速度。

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

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

implode (" AND ", $clauses);

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

下面是一个密切相关的例子:使用SQL MERGE语句使用源表中的所有值更新目标表,源表中没有可以连接的公共属性。

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

使用1=1这样的谓词是一种正常的提示,有时用于强制访问计划使用或不使用索引扫描。使用这种方法的原因是,当您在where子句中使用带有许多谓词的多嵌套连接查询时,有时甚至使用所有索引都会导致访问计划读取每个表—全表扫描。这只是dba用来欺骗dbms使用更有效路径的众多提示之一。只是不要扔进去;您需要dba来分析查询,因为它并不总是有效。

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

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

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

我通常在为一个有许多用户可以选择的下拉值的报告构建动态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+ "'" : "";

由于我们在运行时不知道where子句的选择,所以这在查找是否包含'AND' or 'WHERE'.方面帮助很大

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

我有见过简易框架做这样的事情(脸红),因为这允许将惰性解析实践应用于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的“好处”意味着不需要特殊的代码:

  • 对于 -是否应该应用零、一个或两个谓词(Bars和Baz’s),这将决定是否需要第一个AND。因为我们已经有了至少一个带有1 = 1的谓词,这意味着AND总是可以的。
  • 对于根本没有谓词的情况-在有0个谓词的情况下,那么WHERE必须被删除。但同样,我们可以偷懒,因为我们再次保证至少有一个谓词。

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

如果你来这里搜索WHERE 1,请注意WHERE 1WHERE 1=1是相同的。WHERE 1很少使用,因为一些数据库系统认为WHERE 1不是布尔值而拒绝使用它。

我发现这个模式在我测试或重复检查数据库上的东西时很有用,所以我可以很快地注释其他条件:

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
这在必须使用动态查询in which in where的情况下很有用 子句,则必须附加一些筛选选项。比如,如果你包含选项0表示状态为非活动,1表示活动。根据选项,只有两个可用选项(0和1),但如果您想显示所有记录,可以方便地在close 1=1的位置包含。 参见下面的示例:

Declare @SearchValue    varchar(8)
Declare @SQLQuery varchar(max) = '
Select [FirstName]
,[LastName]
,[MiddleName]
,[BirthDate]
,Case
when [Status] = 0 then ''Inactive''
when [Status] = 1 then ''Active''
end as [Status]'


Declare @SearchOption nvarchar(100)
If (@SearchValue = 'Active')
Begin
Set @SearchOption = ' Where a.[Status] = 1'
End


If (@SearchValue = 'Inactive')
Begin
Set @SearchOption = ' Where a.[Status] = 0'
End


If (@SearchValue = 'All')
Begin
Set @SearchOption = ' Where 1=1'
End


Set @SQLQuery = @SQLQuery + @SearchOption


Exec(@SQLQuery);

回顾了所有的答案,我决定做一些实验

SELECT
*
FROM MyTable


WHERE 1=1

然后我用其他号码核对了一下

WHERE 2=2
WHERE 10=10
WHERE 99=99
< p >等 在完成所有检查之后,查询run town是相同的。即使没有where从句。我不是语法

的粉丝
这是一个用例…然而,我不太关心为什么我应该或不应该使用1 = 1的技术细节。 我正在写一个函数,使用pyodbc从SQL Server检索一些数据。我正在寻找一种方法,在我的代码中的where关键字后强制填充。这确实是一个很好的建议:

if _where == '': _where = '1=1'
...
...
...
cur.execute(f'select {predicate} from {table_name} where {_where}')

原因是我不能在_where子句变量中一起实现关键字“where”。因此,我认为使用任何计算结果为真的虚拟条件都可以作为填充符。

其中1=1"所有查询的标准还使验证SQL变得非常容易,只需将其替换为where 1 = 0,当您有批量命令/文件时非常方便。

这也使得查找任何查询的from/join部分的结尾变得非常容易。甚至带有子查询的查询,如果缩进得当。

在生产代码中看到了这一点,并向前辈寻求帮助。

他们的回答:

-我们使用1=1,所以当我们必须添加一个新的条件时,我们只需输入

and <condition>

然后继续做下去。