细雨如烟不染衣 發表於 2025-5-15 10:54:17

SQL中三值逻辑和NULL的具体使用

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">NULL的特性</a></li><li><a href="#_label1">NULL在SQL逻辑运算中的影响</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">1. 逻辑运算 (AND,&nbsp;OR,&nbsp;NOT)</a></li><li><a href="#_lab2_1_1">2.&nbsp;NULL参与比较 (=,&nbsp;!=,&nbsp;&gt;,&nbsp;&lt;, etc.)</a></li><li><a href="#_lab2_1_2">3.&nbsp;NULL在IN&nbsp;和&nbsp;NOT IN中的影响</a></li><li><a href="#_lab2_1_3">4.&nbsp;NULL在DISTINCT、GROUP BY 和 ORDER BY 中</a></li><li><a href="#_lab2_1_4">5.&nbsp;NULL在 COALESCE 和 IFNULL 处理</a></li></ul><li><a href="#_label2">NULL&nbsp;在 JOIN 中的影响</a></li><ul class="second_class_ul"></ul><li><a href="#_label3">如何正确处理&nbsp;NULL</a></li><ul class="second_class_ul"></ul><li><a href="#_label4">总结(重点)</a></li><ul class="second_class_ul"></ul></ul></div><p>&nbsp;在SQL中,三值逻辑是一个重要概念,它的存在主要是由于&nbsp;<code>NULL</code>&nbsp;值的引入。<code>NULL</code>&nbsp;代表未知值,它既不是空字符串,也不是数字 0,而是一个特殊的标记,表示数据缺失或不可用。</p>
<p>在SQL中,由于<code>NULL</code>值的存在,导致它使用了一种特殊的逻辑作用法:<strong>三值逻辑 (Three-Valued Logic, 3VL)</strong></p>
<p>其包括三个任何逻辑计算的可能结果:</p>
<ul><li><p><strong>TRUE (真)</strong></p></li><li><p><strong>FALSE (假)</strong></p></li><li><p><strong>UNKNOWN (未知)</strong></p></li></ul>
<p><code>NULL</code>在SQL中表示&ldquo;未知&rdquo;或&ldquo;缺失的值&rdquo;,它与普通的值有很大区别。由于<code>NULL</code>表示未知值,所以任何与<code>NULL</code>进行运算的结果都应该是<code>UNKNOWN</code>,而不是TRUE或FALSE。</p>
<p class="maodian"><a name="_label0"></a></p><h2>NULL的特性</h2>
<p><code>NULL</code>并不是一个具体值,而是一个特殊状态,其具有如下特性:</p>
<ul><li><p><code>NULL</code>不能相互比较:<code>NULL = NULL</code>结果不是TRUE,而是UNKNOWN。</p></li><li><p><code>NULL</code>参与数值运算,结果为<code>NULL</code>:<code>NULL + 10</code>的结果仍然是<code>NULL</code>。</p></li><li><p><code>NULL</code>参与逻辑运算,会影响逻辑结果:</p>
<ul><li><p><code>TRUE AND NULL</code>,结果是<code>UNKNOWN</code></p></li><li><p><code>FALSE OR NULL</code>,结果是<code>UNKNOWN</code></p></li></ul></li></ul>
<p>如果WHERE条件结果为<code>UNKNOWN</code>,那么该记录将不会被查询结果包含。</p>
<p class="maodian"><a name="_label1"></a></p><h2>NULL在SQL逻辑运算中的影响</h2>
<p class="maodian"><a name="_lab2_1_0"></a></p><h3>1. 逻辑运算 (AND,&nbsp;OR,&nbsp;NOT)</h3>
<p>AND运算</p>
<table><tbody><tr><th>表达式</th><th>结果</th></tr><tr><td>TRUE AND TRUE</td><td>TRUE</td></tr><tr><td>TRUE AND FALSE</td><td>FALSE</td></tr><tr><td>TRUE AND UNKNOWN</td><td>UNKNOWN</td></tr><tr><td>FALSE AND UNKNOWN</td><td>FALSE</td></tr><tr><td>UNKNOWN AND UNKNOWN</td><td>UNKNOWN</td></tr></tbody></table>
<p>&nbsp;OR运算</p>
<table><tbody><tr><th>表达式</th><th>结果</th></tr><tr><td>TRUE OR UNKNOWN</td><td>TRUE</td></tr><tr><td>FALSE OR UNKNOWN</td><td>UNKNOWN</td></tr><tr><td>UNKNOWN OR UNKNOWN</td><td>UNKNOWN</td></tr></tbody></table>
<p>NOT运算&nbsp;</p>
<table><tbody><tr><th>表达式</th><th>结果</th></tr><tr><td>NOT TRUE</td><td>FALSE</td></tr><tr><td>NOT FALSE</td><td>TRUE</td></tr><tr><td>NOT UNKNOWN</td><td>UNKNOWN</td></tr></tbody></table>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>2.&nbsp;NULL参与比较 (=,&nbsp;!=,&nbsp;&gt;,&nbsp;&lt;, etc.)</h3>
<table><tbody><tr><th>表达式</th><th>结果</th></tr><tr><td>NULL = NULL</td><td>UNKNOWN</td></tr><tr><td>NULL != NULL</td><td>UNKNOWN</td></tr><tr><td>NULL &gt; 10</td><td>UNKNOWN</td></tr><tr><td>NULL &lt; 10</td><td>UNKNOWN</td></tr><tr><td>NULL IS NULL</td><td>TRUE</td></tr><tr><td>NULL IS NOT NULL</td><td>FALSE</td></tr></tbody></table>
<p class="maodian"><a name="_lab2_1_2"></a></p><h3>3.&nbsp;NULL在IN&nbsp;和&nbsp;NOT IN中的影响</h3>
<p>如果&nbsp;<code>NULL</code>&nbsp;出现在&nbsp;<code>IN</code>&nbsp;或&nbsp;<code>NOT IN</code>&nbsp;语句中,会导致不可预期的结果:</p>
<div class="jb51code"><pre class="brush:sql;">SELECT * FROM users WHERE age IN (20, 30, NULL);</pre></div>
<p>由于&nbsp;<code>NULL</code>&nbsp;是未知值,SQL 不知道&nbsp;<code>NULL</code>&nbsp;是否属于&nbsp;<code>age</code>,导致&nbsp;<code>UNKNOWN</code>,最终查询只会匹配&nbsp;<code>age=20</code>&nbsp;和&nbsp;<code>age=30</code>,但不会匹配&nbsp;<code>NULL</code>。</p>
<p>更严重的问题出现在&nbsp;<code>NOT IN</code>&nbsp;中:</p>
<div class="jb51code"><pre class="brush:sql;">SELECT * FROM users WHERE age NOT IN (20, 30, NULL);</pre></div>
<p>由于&nbsp;<code>NULL</code>&nbsp;在&nbsp;<code>IN</code>&nbsp;语句中会返回&nbsp;<code>UNKNOWN</code>,整个&nbsp;<code>NOT IN</code>&nbsp;变成&nbsp;<code>UNKNOWN</code>,最终不会返回任何数据。</p>
<p>解决方法:</p>
<div class="jb51code"><pre class="brush:sql;">SELECT * FROM users WHERE age NOT IN (20, 30) OR age IS NULL;</pre></div>
<p class="maodian"><a name="_lab2_1_3"></a></p><h3>4.&nbsp;NULL在DISTINCT、GROUP BY 和 ORDER BY 中</h3>
<ul><li><p><strong>DISTINCT</strong>&nbsp;视&nbsp;<code>NULL</code>&nbsp;为相同值:</p>
<div class="jb51code"><pre class="brush:sql;">SELECT DISTINCT category FROM products;</pre></div>
<p>如果&nbsp;<code>category</code>&nbsp;列中有多个&nbsp;<code>NULL</code>,<code>DISTINCT</code>&nbsp;只会保留一个&nbsp;<code>NULL</code>。</p></li><li><p><strong>GROUP BY</strong>&nbsp;视&nbsp;<code>NULL</code>&nbsp;为一个分组:</p>
<div class="jb51code"><pre class="brush:sql;">SELECT category, COUNT(*) FROM products GROUP BY category;</pre></div>
<p>所有&nbsp;<code>NULL</code>&nbsp;值会被归为同一组。</p></li><li><p><strong>ORDER BY</strong>&nbsp;处理&nbsp;<code>NULL</code>:</p>
<div class="jb51code"><pre class="brush:sql;">SELECT * FROM employees ORDER BY salary ASC;</pre></div>
<p><code>NULL</code>&nbsp;默认排在最前或最后,具体行为取决于数据库:</p>
<ul><li><p>PostgreSQL:&nbsp;<code>NULLS FIRST</code>&nbsp;或&nbsp;<code>NULLS LAST</code></p></li><li><p>MySQL:&nbsp;<code>NULL</code>&nbsp;默认排在最前</p></li><li><p>SQL Server:&nbsp;<code>NULL</code>&nbsp;默认排在最前</p></li></ul></li></ul>
<p class="maodian"><a name="_lab2_1_4"></a></p><h3>5.&nbsp;NULL在 COALESCE 和 IFNULL 处理</h3>
<p>要避免&nbsp;<code>NULL</code>&nbsp;影响查询,可以使用&nbsp;<code>COALESCE</code>&nbsp;或&nbsp;<code>IFNULL</code>&nbsp;进行处理:</p>
<ul><li><p><code>COALESCE(expr1, expr2, ..., exprN)</code>:返回第一个非NULL值</p>
<div class="jb51code"><pre class="brush:sql;">SELECT name, COALESCE(email, '未知') AS email FROM users;</pre></div></li><li><p><code>IFNULL(expr, default_value)</code>(MySQL 专用)</p>
<div class="jb51code"><pre class="brush:sql;">SELECT name, IFNULL(email, '未知') AS email FROM users;</pre></div></li></ul>
<p class="maodian"><a name="_label2"></a></p><h2>NULL&nbsp;在 JOIN 中的影响</h2>
<p>如果&nbsp;<code>NULL</code>&nbsp;存在于&nbsp;<code>JOIN</code>&nbsp;的关联列中,则该行不会被匹配:</p>
<div class="jb51code"><pre class="brush:sql;">SELECT * FROM orders
LEFT JOIN customers ON orders.customer_id = customers.id;</pre></div>
<p>如果&nbsp;<code>orders.customer_id</code>&nbsp;是&nbsp;<code>NULL</code>,<code>= NULL</code>&nbsp;结果是&nbsp;<code>UNKNOWN</code>,导致&nbsp;<code>INNER JOIN</code>&nbsp;失败。</p>
<p><code>LEFT JOIN</code>&nbsp;可以保留&nbsp;<code>orders</code>&nbsp;但&nbsp;<code>customers</code>&nbsp;数据为&nbsp;<code>NULL</code>。</p>
<p class="maodian"><a name="_label3"></a></p><h2>如何正确处理&nbsp;NULL</h2>
<ul><li><p>查询时使用&nbsp;IS NULL&nbsp;和&nbsp;IS NOT NULL</p>
<div class="jb51code"><pre class="brush:sql;">SELECT * FROM users WHERE email IS NULL;</pre></div></li><li><p>避免&nbsp;NULL&nbsp;影响逻辑运算</p>
<div class="jb51code"><pre class="brush:sql;">SELECT * FROM orders WHERE discount IS NULL OR discount &gt; 10;</pre></div></li><li><p>在&nbsp;JOIN&nbsp;中考虑&nbsp;NULL&nbsp;可能带来的问题</p>
<div class="jb51code"><pre class="brush:sql;">SELECT * FROM orders
LEFT JOIN customers ON orders.customer_id = customers.id
WHERE customers.id IS NOT NULL;</pre></div></li><li><p>使用&nbsp;COALESCE()&nbsp;处理&nbsp;NULL</p>
<div class="jb51code"><pre class="brush:sql;">SELECT name, COALESCE(email, '未知') AS email FROM users;</pre></div></li><li><p>正确使用&nbsp;NOT IN</p>
<div class="jb51code"><pre class="brush:sql;">SELECT * FROM users WHERE age NOT IN (20, 30) OR age IS NULL;</pre></div></li></ul>
<p class="maodian"><a name="_label4"></a></p><h2>总结(重点)</h2>
<ul><li>NULL&nbsp;代表未知,不是空字符串或 0。</li><li>SQL 采用三值逻辑(TRUE, FALSE, UNKNOWN),导致&nbsp;NULL&nbsp;参与运算时可能返回&nbsp;UNKNOWN。</li><li>NULL&nbsp;不能用&nbsp;=&nbsp;直接比较,而要使用&nbsp;IS NULL&nbsp;和&nbsp;IS NOT NULL。</li><li>NULL&nbsp;可能影响&nbsp;JOIN、GROUP BY、ORDER BY、IN/NOT IN&nbsp;等查询,必须小心处理。</li><li>使用&nbsp;COALESCE()、IFNULL()&nbsp;等函数可以避免&nbsp;NULL&nbsp;带来的问题。</li></ul>
頁: [1]
查看完整版本: SQL中三值逻辑和NULL的具体使用