程序员必知:为什么SQL中常用where 1=1及其潜在风险解析
程序员在编程时,常常会在代码里使用“where 1=1”。那这究竟是为何呢?

[id_598457631]
初次看到这种写法的同学肯定会感到纳闷,那就是加不加 where 1=1 ,在查询方面难道不是都一样吗?例如:
select * from customers;与select * from customers where 1=1;
查询出来的结果完全没有区别呀。
上面的查询结果是没有区别。然而,这并非我们添加它的目的。我们清楚 1 = 1 表示 true,也就是永真。在进行 SQL 注入时,配合 or 运算符会得出意想不到的结果。
对客户名称为“张三”的记录进行删除操作。
delete from customers where name='张三'
这个时候在 where 语句后面加上 or 1=1会有什么样的后果呢?
即:
delete from customers where name='张三' or 1=1
原本只需删除张三的记录,然而由于添加了 or 1=1 这样的永真条件,就会致使整张表中的记录都被删除掉。
这种事我们绝对不能做,也不能给别人可乘之机,这里只是为了说明 where 1=1 的其中一个作用。
语法规范
我们在写代码时,为了确保语法规范,有时会使用到 where 1=1。
我们先看下面这段Java代码:
String sql="select * from table_name where 1=1";if( condition 1) {sql=sql+" and var2=value2";}if(condition 2) {sql=sql+" and var3=value3";}
如果不写 1 = 1 ,在 condition 1 为真的情况下,代码拼接后被执行的 SQL 代码如下:
select * from table_name where and var2=value2;
这里很明显会出现一个 SQL 的语法错误,具体表现为 and 必须前后都有条件。
有人说我将 where 写在了 if 语句里面,而没有写 where 1=1 。
String sql="select * from table_name";if( condition 1) {sql=sql+" where var2=value2 ";}if(condition 2) {sql=sql+" where var3=value3";}
当 condition 1 处于真的状态,而 condition 2 处于假的状态时,被执行的上述 SQL 代码是:
select * from table_name where var2=value2;
这个没有语法错误。然而,当 condition1 和 condition2 都为真时,SQL 语句会变成这样。
select * from table_namewhere var2=value2where var3=value3;
很明显这是不符合SQL语法规范的。
这里写上 1 = 1 是为了避免 where 关键字后面的首个词直接为“and”从而引发语法错误。当加上 1 = 1 后,无论后面是否有 and 条件,都不会导致语法错误了。
拷贝表
我们进行数据备份时,经常会用到 where 1=1。其实这部分内容可以不写。如果想要在备份时过滤一些数据,那么写上 where 1=1 之后会比较方便,只需直接在后面添加 and 条件就可以了。
create table table_nameasselect * from Source_tablewhere 1=1;
复制表结构
有 1 等于 1 这种情况时,就会出现 11 或者 1 等于 2 这样永远为假的条件。在拷贝表的时候,加上 where 11 这个条件,意味着没有任何一条记录能够满足该条件。通过这样的方式,我们就能够只拷贝表的结构,而不拷贝数据了。
create table table_nameasselect * fromSource_table where 1 <> 1;
1=1的性能问题
在 MySQL 早期版本里,“where 1=1”可能会产生影响。使用了“where 1=1”的过滤条件后,数据系统就不能使用索引等查询优化策略了。数据库系统会被迫对每行数据进行扫描,也就是全表扫描,以此来比较此行是否满足过滤条件。当表中数据量较大时,查询速度会很慢。
在 5.6 版本(或许更早几个版本之后),这个问题得到了优化。当写“where 1=1”时,查询分析器会把“1=1”处理掉,因此不会对查询的性能产生影响。感兴趣的小伙伴可以进行试验,我已经试过了。
作者丨丶平凡世界