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

我在某处看到这将用于防止 SQL 注入,但这看起来很奇怪。

如果有注射 WHERE 1 = 1 AND injected OR 1=1 会有相同的结果 injected OR 1=1.

稍后编辑:视图定义中的用法怎么样?


谢谢您的回答。

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

以此为例:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value
有帮助吗?

解决方案

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

and <condition>

并将它们连接在一起。在开始时使用 1 = 1 ,初始可以关联。

我从来没有见过这种用于任何注射防护的东西,正如你所说它看起来似乎不会有多大帮助。我已经看到它用作实现方便。 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

我已经看到它在条件数量可变的情况下使用。

您可以使用“&quot;”连接条件。 AND“和串。然后,不是计算你传入的条件数,而是放置一个“WHERE 1 = 1”。在库存SQL语句的末尾,并抛出连接条件。

基本上,它可以节省您必须对条件进行测试然后添加“WHERE”的条件。他们之前的字符串。

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

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

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

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

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

其中1 = 0,这样做是为了检查表是否存在。不知道为什么使用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 并检查:

  • 我的名字是鲍勃;和
  • 工资> $20,000

有些人会在第一个添加 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

我在测试或仔细检查数据库上的内容时发现这种模式很有用,所以我可以非常快速地评论其他条件:

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

因此避免了前导或尾随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;

为什么有人会使用 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 总是可以的。
  • 对于根本没有谓词 - 在有零个谓词的情况下,那么 WHERE 必须被丢弃。但同样,我们可以偷懒,因为我们再次保证至少一个谓词。

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

如果您来到这里搜索 WHERE 1 ,请注意 WHERE 1 WHERE 1 = 1 是相同的。 WHERE 1 很少使用,因为某些数据库系统拒绝它,因为 WHERE 1 并不是真正的布尔值。

这在您必须使用动态查询的情况下非常有用 你必须附加一些过滤器选项。就像你包含选项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

ECT 完成所有检查后,查询运行城镇是相同的。即使没有where子句。我不是语法的粉丝

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

我通常在为具有许多用户可以选择的下拉值的报表构建动态SQL时执行此操作。由于用户可能会或可能不会从每个下拉列表中选择值,因此我们最终难以确定哪个条件是第一个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'或'WHERE'。

我第一次看到ADO和经典的asp,我得到的答案是:性能。 如果你直接

从tablename

中选择*

并将其作为sql命令/文本传递,您将通过

获得显着的性能提升

其中1 = 1

补充说,这是一个明显的差异。一旦满足第一个条件就会返回表标题,或者其他一些疯狂,无论如何,它确实加快了速度。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top