SQL 语句中 Where 条件后 写上1=1 是什么意思
<p><img title="SQL 语句中 Where 条件后 写上1=1 是什么意思" alt="SQL 语句中 Where 条件后 写上1=1 是什么意思" border="0" src="https://zhuji.jb51.net/uploads/img/202305/324dc3087189141b2516fd57eb05bcce.jpg"></p>
<p>
程序员在编程过程中,经常会在代码中使用到“where 1=1”,这是为什么呢?</p>
<h3>
SQL注入</h3>
<p>
初次看到这种写法的同学肯定很纳闷,加不加where 1=1,查询不都一样吗?例如:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span>*</span><span class="keyword">from</span><span>customers;</span></span>
</li>
<li>
<span>与</span>
</li>
<li class="alt">
<span><span class="keyword">select</span><span>*</span><span class="keyword">from</span><span>customers</span><span class="keyword">where</span><span>1=1;</span></span>
</li>
</ol>
<p>
查询出来的结果完全没有区别呀。</p>
<p>
是的,上面的查询结果是没有区别,但是这并不是我们要添加它的目的。我们知道1=1表示true,即永真,在SQL注入时配合or运算符会得到意向不到的结果。</p>
<p>
例如,当我们要删除客户名称为“张三”的记录,我们可以这样写:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">delete</span><span class="keyword">from</span><span>customers</span><span class="keyword">where</span><span class="keyword">name</span><span>=</span><span class="string">'张三'</span></span>
</li>
</ol>
<p>
这个时候如果在where语句后面加上 or 1=1会是什么后果?</p>
<p>
即:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">delete</span><span class="keyword">from</span><span>customers</span><span class="keyword">where</span><span class="keyword">name</span><span>=</span><span class="string">'张三'</span><span class="op">or</span><span>1=1</span></span>
</li>
</ol>
<p>
本来只要删除张三的记录,结果因为添加了or 1=1的永真条件,会导致整张表里的记录都被删除了。</p>
<p>
当然这种事我们可千万不能干,也不能让别人有机可乘,这里只是为了表述where 1=1的作用之一。</p>
<h3>
语法规范</h3>
<p>
我们在写代码的过程中,为了保证语法规范的时候,也会使用到where 1=1。</p>
<p>
我们先看下面这段Java代码:</p>
<ol class="dp-sql">
<li class="alt">
<span><span>Stringsql=</span><span class="string">"select*fromtable_namewhere1=1"</span><span>;</span></span>
</li>
<li>
<span>if(condition1){</span>
</li>
<li class="alt">
<span>sql=sql+<span class="string">"andvar2=value2"</span><span>;</span></span>
</li>
<li>
<span>}</span>
</li>
<li class="alt">
<span>if(condition2){</span>
</li>
<li>
<span>sql=sql+<span class="string">"andvar3=value3"</span><span>;</span></span>
</li>
<li class="alt">
<span>}</span>
</li>
</ol>
<p>
如果我们不写1=1的话,当condition 1为真时,代码拼接后被执行的SQL代码如下:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span>*</span><span class="keyword">from</span><span>table_name</span><span class="keyword">where</span><span class="op">and</span><span>var2=value2;</span></span>
</li>
</ol>
<p>
很明显,这里会出现一个SQL 的语法错误:and必须前后都有条件。</p>
<p>
有人说我直接把where写在if语句里面,我就不写where 1=1。</p>
<ol class="dp-sql">
<li class="alt">
<span><span>Stringsql=</span><span class="string">"select*fromtable_name"</span><span>;</span></span>
</li>
<li>
<span>if(condition1){</span>
</li>
<li class="alt">
<span>sql=sql+<span class="string">"wherevar2=value2"</span><span>;</span></span>
</li>
<li>
<span>}</span>
</li>
<li class="alt">
<span>if(condition2){</span>
</li>
<li>
<span>sql=sql+<span class="string">"wherevar3=value3"</span><span>;</span></span>
</li>
<li class="alt">
<span>}</span>
</li>
</ol>
<p>
当condition 1为真,condition 2为假时,上面被执行的SQL代码为:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span>*</span><span class="keyword">from</span><span>table_name</span><span class="keyword">where</span><span>var2=value2;</span></span>
</li>
</ol>
<p>
这个确实没有语法错误,但是当condition 1和condition 2都为真呢?那么SQL语句就变成了这样:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span>*</span><span class="keyword">from</span><span>table_name</span></span>
</li>
<li>
<span><span class="keyword">where</span><span>var2=value2</span></span>
</li>
<li class="alt">
<span><span class="keyword">where</span><span>var3=value3;</span></span>
</li>
</ol>
<p>
很明显这是不符合SQL语法规范的。</p>
<p>
这里写上where 1=1 是为了避免where 关键字后面的第一个词直接就是 “and”而导致语法错误,加上1=1后,不管后面有没有and条件都不会造成语法错误了。</p>
<h3>
拷贝表</h3>
<p>
在我们进行数据备份时,也经常使用到where 1=1,当然其实这两可以不写,写上之后如果想过滤一些数据再备份会比较方便,直接在后面添加and条件即可。</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">create</span><span class="keyword">table</span><span>table_name</span></span>
</li>
<li>
<span><span class="keyword">as</span></span>
</li>
<li class="alt">
<span><span class="keyword">select</span><span>*</span><span class="keyword">from</span><span>Source_table</span></span>
</li>
<li>
<span><span class="keyword">where</span><span>1=1;</span></span>
</li>
</ol>
<h3>
复制表结构</h3>
<p>
有1=1就会有1<>1或1=2之类的永假的条件,这个在拷贝表的时候,加上where 1<>1,意思就是没有任何一条记录符合条件,这样我们就可以只拷贝表结构,不拷贝数据了。</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">create</span><span class="keyword">table</span><span>table_name</span></span>
</li>
<li>
<span><span class="keyword">as</span></span>
</li>
<li class="alt">
<span><span class="keyword">select</span><span>*</span><span class="keyword">from</span></span>
</li>
<li>
<span>Source_table<span class="keyword">where</span><span>1<>1;</span></span>
</li>
</ol>
<h3>
1=1的性能问题</h3>
<p>
在MySQL早期的版本中“ where 1=1”可能会对有所影响,使用了“where 1=1”的过滤条件以后数据系统就无法使用索引等查询优化策略,数据库系统将会被迫对每行数据进行扫描(即全表扫描)以比较此行是否满足过滤条件,当表中数据量较大时查询速度会非常慢。</p>
<p>
但在5.6版本(也可能更早几个版本)以后这个问题被优化了,在写“where 1=1”时,查询分析器会将“1=1”处理掉,所以不会对查询造成性能影响,感兴趣的小伙伴可以试验一下,反正我试过了。</p>
<p>
原文链接:https://mp.weixin.qq.com/s/HYnkxoQLcpVByydVrL7lBA</p>
頁:
[1]