ChatGPT解决这个技术问题 Extra ChatGPT

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

为什么有人会在 SQL 子句中使用 WHERE 1=1 AND <conditions>(通过连接字符串获得的 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
“为什么有人会使用这种结构来定义视图”可能是出于习惯。它在静态查询中没有任何功能优势。

G
Greg Hewgill

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

and <condition>

并将它们连接在一起。以 1=1 开头,最初的 and 有一些关联。

我从未见过它用于任何类型的注射保护,正如你所说,它似乎没有多大帮助。我已经看到它被用作实现便利。 SQL 查询引擎最终会忽略 1=1,因此它不会对性能产生影响。


有时不是懒惰,而是拥有更简洁的代码。
处理尾随 AND 或 COMMA 并不肮脏……没有什么比 SQL 中的 1=1 更干净了。
数据库管理员?它们是干什么用的? :)
DBA 会在程序员认为他们知道如何有效地使用数据库之后进行清理。
“懒惰” 我喜欢认为它很聪明,而不是懒惰。您正在避免重复代码和不必要的条件检查。由于无法添加 where 1=1 (Oracle) 或 where true (Postgres),我将不得不检查每个条件是否是第一个条件。这样做没有意义,它只会添加更多样板代码。
T
Tim

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

有点hacky,但似乎是一个有效的用途。
这应该是公认的答案。这种做法实际上只是为了不必确定你有多少条件。
C
Carl

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

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

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


J
John Lemp

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


“懒惰” 我喜欢认为它很聪明,而不是懒惰。您正在避免重复代码和不必要的条件检查。由于无法添加 where 1=1 (Oracle) 或 where true (Postgres),我将不得不检查每个条件是否是第一个条件。这样做没有意义,它只会添加更多样板代码。
@ADTC 编写代码通常(如果不是主要的话)是关于处理不同的条件。这只是需要处理的另一个条件,我个人认为这是懒惰来污染生成的 SQL。如果您将代码设计为在一个位置添加“Where 1 = 1”,您可以 - 无需额外努力 - 处理代码中该位置的零和多个条件之间的差异。不过,我的猜测是,“Where 1 = 1”的倡导者将它洒在他们的代码库中,这让我得出了懒惰滋生懒惰的结论。
@JasonS Laziness 是发明之父。
@ADTC我很懒,因为我不喜欢在数百个地方更新代码,所以发明将它放在一个地方。对我而言,WHERE 1=1 产生了在多个位置维护相同代码并在所有生成的 SQL 中读取它的额外工作。我比你想象的还要懒!
D
DatumPoint

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

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

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


忘了添加,虽然它会创建一个与旧表具有相同数据的新表,但新表不会有其他约束,如旧表中的外键
a
aku

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


T
Tim

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

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

p
paxdiablo

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

“懒惰” 我喜欢认为它很聪明,而不是懒惰。您正在避免重复代码和不必要的条件检查。由于无法添加 where 1=1 (Oracle) 或 where true (Postgres),我将不得不检查每个条件是否是第一个条件。这样做没有意义,它只会添加更多样板代码。
@ADTC,我并不是说懒惰。事实上,懒惰是编程中的一个很好的特征:-) 我会澄清的。
懒惰是万恶之源
佚名

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


看到这用于从数据库返回一个空结果集,用作新记录的持有者。
s
sanbikinoraion

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

implode (" AND ", $clauses);

从而避免出现前导或尾随 AND 的问题。显然,这仅在您知道您将拥有至少一个子句时才有用!


这就是 1=1 的用武之地。它为您提供了“至少一个子句”,因此您不必担心只是拍打“ AND abc”
我喜欢这个主意!有关更完整的示例 stackoverflow.com/questions/35326160/…,请参见此处
o
onedaywhen

这是一个密切相关的示例:使用 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;

Y
Yogesh Umesh Vaity

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


C
Community

为什么有人会使用 WHERE 1=1 AND

我有 seen 个自制框架做这样的事情 (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's),这将确定是否需要第一个 AND。由于我们已经有至少一个 1 = 1 的谓词,这意味着 AND 总是可以的。

对于根本没有谓词 - 如果谓词为零,则必须删除 WHERE。但同样,我们可以偷懒,因为我们再次保证了至少一个谓词。

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


或者,如果您自己滚动,where 子句构建器应该在您的代码中的一个位置。然后,您可以在代码中的单个位置处理零个谓词或多个谓词。我的怀疑是 WHERE 1=1 的存在是一个公平的指标,表明情况并非如此,代码库中到处都是字符串 WHERE 1=1,这对我来说表明存在应用程序架构问题,我猜不是唯一的!
实际上,这个想法并没有什么“坏处”,更不用说“明显”的错误了。在所有情况下,ORM 也不是正确的方法。学习 SQL 和关系代数的人...
J
JonWay

查看所有答案后,我决定进行一些实验,例如

SELECT
*
FROM MyTable

WHERE 1=1

然后我检查了其他号码

WHERE 2=2
WHERE 10=10
WHERE 99=99

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


E
Eliseo Jr

这在您必须使用动态查询的情况下很有用,其中在 where 子句中您必须附加一些过滤器选项。就像如果您包含选项 0 状态为非活动状态,1 为活动状态。根据选项,只有两个可用选项(0 和 1),但如果要显示所有记录,可以方便地包含在 where 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);

B
Bora Çolakoğlu

在生产代码中看到这个,请前辈帮忙。

他们的回答:

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

and <condition>

继续做下去。


Z
Zo Has

我通常在为具有许多用户可以选择的下拉值的报表构建动态 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'.


s
spioter

使“where 1=1”成为所有查询的标准还可以通过将其替换为 where 1 = 0 来轻松验证 sql,这在您有成批的命令/文件时很方便。

还可以很容易地找到任何查询的 from/join 部分的结尾。如果缩进正确,即使是带有子查询的查询。


j
jackberry

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

Select * from tablename

并将其作为 sql 命令/文本传递,您将获得显着的性能提升

Where 1=1

补充说,这是一个明显的差异。与第一个条件满足后立即返回表头有关,或者其他一些疯狂的事情,无论如何,它确实加快了速度。


如果这是真的,为什么 DBMS 不总是添加它?
我也看到了这个,但很抱歉我无法指定引擎/版本。这是我 20 多年 sql 编码中的某个时刻。我认为发生的事情是没有任何 Where 子句,执行计划最终进行了表扫描;添加 where 1 =1 会产生更好的计划。但 anedote <> data 的复数;我不能发誓根本问题不是临时网络或其他资源问题:-p
S
Soner Gönül

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


您是否有任何引用记录了某些数据库的这种行为?
S
SMS

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

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

原因是我无法在 _where 子句变量中同时实现关键字“where”。所以,我认为使用任何评估为 true 的虚拟条件都可以作为填充物。