驎驎 發表於 2025-10-28 10:05:06

如何在SQL中实现表的增删

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">1.增</a></li><ul class="second_class_ul"><li><a href="#_lab2_0_0">1.1 create</a></li><li><a href="#_lab2_0_1">1.2 全列插入</a></li><li><a href="#_lab2_0_2">1.3 指定列插入</a></li><li><a href="#_lab2_0_3">1.4插入否则更新(duplicate)</a></li><li><a href="#_lab2_0_4">1.5替换(replace)</a></li><li><a href="#_lab2_0_5">1.7 deplicate和replace的区别</a></li><ul class="third_class_ul"><li><a href="#_label3_0_5_0">1.7.1核心操作逻辑不同</a></li><li><a href="#_label3_0_5_1">1.7.2对自增主键的影响不同</a></li><li><a href="#_label3_0_5_2">1.7.3对未指定字段的处理不同</a></li><li><a href="#_label3_0_5_3">1.7.4示例对比</a></li><li><a href="#_label3_0_5_4">1.7.5适用场景</a></li><li><a href="#_label3_0_5_5">总结</a></li></ul></ul><li><a href="#_label1">2. 删</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_6">2.1 删除表(delete)</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_1_7">2.2 截断表(truncate)</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_1_8">2.3 删除的注意点</a></li><ul class="third_class_ul"></ul></ul></ul></div><p>今天我们来聊一下表的增删。对于数据表来说,数据是非常重要的,所以关于数据的增删也是非常重要的。</p>
<p class="maodian"><a name="_label0"></a></p><h2>1.增</h2>
<p class="maodian"><a name="_lab2_0_0"></a></p><h3>1.1 create</h3>
<p>下面这张图就是create的使用方式。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202510/2025102809595239.jpg" /></p>
<p class="maodian"><a name="_lab2_0_1"></a></p><h3>1.2 全列插入</h3>
<p>下面这张图就是全列插入,意思就是说给这张表里面的每一个数据都插入值。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202510/2025102809595214.png" /></p>
<p class="maodian"><a name="_lab2_0_2"></a></p><h3>1.3 指定列插入</h3>
<p>下面这张图就是指定列插入,我们在这里给a1和a2插入了值。那么我们在查看的时候就会发现在这张表的第二行的a3位置就是NULL。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202510/2025102809595240.png" /></p>
<p class="maodian"><a name="_lab2_0_3"></a></p><h3>1.4插入否则更新(duplicate)</h3>
<p><span><strong>具体语法:</strong></span></p>
<div class="jb51code"><pre class="brush:sql;">INSERT ... ON DUPLICATE KEY UPDATE column = value [, column = value] ...</pre></div>
<p>我们在插入值的时候如果给主键或唯一键插入了一样的值那么就会报错。就像下面这样。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202510/2025102809595230.png" /></p>
<p>这个时候我们就可以使用这个指令在发生冲突的时候来进行更新,通过额外添加的&nbsp;on duplicate key update a2=15,a3=150;我们就可以实现修改其已被主键占用的那一行值。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202510/2025102809595295.png" /></p>
<p class="maodian"><a name="_lab2_0_4"></a></p><h3>1.5替换(replace)</h3>
<blockquote><div><span>主键 或者 唯一键 没有冲突,则直接插入; </span></div>
<p><span>主键 或者 唯一键 如果冲突,则删除后再插入 </span></p></blockquote>
<p>当主键或者唯一键没用冲突的时候它就会直接插入数据。</p>
<div><img alt="" src="https://img.jbzj.com/file_images/article/202510/2025102809595226.png" /></div>
<p>我们看下面这张图,我们使用replace那么就可以直接更改主键的那一行值。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202510/2025102809595294.png" /></p>
<p>我们也可以根据指令执行完后的那一行语句来确定是直接插入还是删除后插入。</p>
<blockquote><p><span>-- 1 row affected: 表中没有冲突数据,数据被插入 </span></p>
<p><span>-- 2 row affected: 表中有冲突数据,删除后重新插入</span></p></blockquote>
<p class="maodian"><a name="_lab2_0_5"></a></p><h3>1.7 deplicate和replace的区别</h3>
<p class="maodian"><a name="_label3_0_5_0"></a></p><h4>1.7.1核心操作逻辑不同</h4>
<ul><li><code>REPLACE</code>:当插入的数据与表中现有数据发生唯一键冲突时,会先删除表中已存在的冲突行,然后插入新行。本质上等价于执行了&nbsp;<code>DELETE</code>&nbsp;+&nbsp;<code>INSERT</code>&nbsp;两个操作。</li><li><code>ON DUPLICATE KEY UPDATE</code>:当插入的数据发生唯一键冲突时,不会删除原有行,而是直接更新原有行中指定的字段。本质上等价于执行了&nbsp;<code>UPDATE</code>&nbsp;操作(仅针对冲突行)。</li></ul>
<p class="maodian"><a name="_label3_0_5_1"></a></p><h4>1.7.2对自增主键的影响不同</h4>
<ul><li><code>REPLACE</code>:由于会先删除冲突行再插入新行,若表使用自增主键,新插入的行会生成新的自增 ID(<span>原有 ID 被废弃,不会重复使用</span>)。例如:原有行&nbsp;<code>id=1</code>&nbsp;冲突,<code>REPLACE</code>&nbsp;后新行可能是&nbsp;<code>id=2</code>(自增 ID 递增)。</li><li><code>ON DUPLICATE KEY UPDATE</code>:仅更新原有行,不会删除数据,因此自增主键的值保持不变。例如:原有行&nbsp;<code>id=1</code>&nbsp;冲突,更新后仍为&nbsp;<code>id=1</code>。</li></ul>
<p class="maodian"><a name="_label3_0_5_2"></a></p><h4>1.7.3对未指定字段的处理不同</h4>
<ul><li><code>REPLACE</code>:插入新行时,若新数据中未明确指定某些字段,这些字段会使用表定义的默认值(或&nbsp;<code>NULL</code>),覆盖原有行的值。例如:原有行有&nbsp;<code>age=20</code>,但&nbsp;<code>REPLACE</code>&nbsp;语句未指定&nbsp;<code>age</code>,则新行的&nbsp;<code>age</code>&nbsp;会变为默认值(如&nbsp;<code>NULL</code>)。</li><li><code>ON DUPLICATE KEY UPDATE</code>:仅更新&nbsp;<code>UPDATE</code>&nbsp;子句中明确指定的字段,未指定的字段保持原有值不变。例如:原有行&nbsp;<code>age=20</code>,<code>UPDATE</code>&nbsp;仅指定更新&nbsp;<code>name</code>,则&nbsp;<code>age</code>&nbsp;仍为 20。</li></ul>
<p class="maodian"><a name="_label3_0_5_3"></a></p><h4>1.7.4示例对比</h4>
<p>假设有表&nbsp;<code>student</code>&nbsp;结构如下:</p>
<div class="jb51code"><pre class="brush:sql;">CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) UNIQUE, -- 唯一索引,可能冲突
score INT
);
</pre></div>
<p>已有数据:<code>(id=1, name=&#39;Tom&#39;, score=80)</code></p>
<p>场景:插入&nbsp;<code>name=&#39;Tom&#39;</code>&nbsp;的新数据(冲突)</p>
<p>使用&nbsp;<code>REPLACE</code>:</p>
<div class="jb51code"><pre class="brush:sql;">REPLACE INTO student (name, score) VALUES ('Tom', 90);
</pre></div>
<p>执行后结果:</p>
<p>原有行&nbsp;<code>(1, &#39;Tom&#39;, 80)</code>&nbsp;被删除。</p>
<p>插入新行&nbsp;<code>(2, &#39;Tom&#39;, 90)</code>(id 变为 2,自增 ID 递增)。</p>
<p>使用&nbsp;<code>ON DUPLICATE KEY UPDATE</code>:</p>
<div class="jb51code"><pre class="brush:sql;">INSERT INTO student (name, score) VALUES ('Tom', 90)
ON DUPLICATE KEY UPDATE score = VALUES(score);
</pre></div>
<p>执行后结果:</p>
<p>原有行&nbsp;<code>(1, &#39;Tom&#39;, 80)</code>&nbsp;被更新为&nbsp;<code>(1, &#39;Tom&#39;, 90)</code>(id 保持 1,仅更新&nbsp;<code>score</code>)。</p>
<p class="maodian"><a name="_label3_0_5_4"></a></p><h4>1.7.5适用场景</h4>
<ul><li><code>REPLACE</code>:适合需要完全替换冲突行(包括未指定字段使用默认值)的场景,但需注意自增 ID 变化的影响(可能导致 ID 不连续)。</li><li><code>ON DUPLICATE KEY UPDATE</code>:适合仅更新部分字段、保留其他原有数据的场景,效率更高(无需删除操作),且不会改变自增 ID。</li></ul>
<p class="maodian"><a name="_label3_0_5_5"></a></p><h4>总结</h4>
<p>两者的核心区别在于:<code>REPLACE</code>&nbsp;是 &ldquo;删旧插新&rdquo;,会改变行的存在性和自增 ID;<code>ON DUPLICATE KEY UPDATE</code>&nbsp;是 &ldquo;原地更新&rdquo;,仅修改指定字段,保留原有行的其他属性。选择时需根据是否需要保留原有数据、自增 ID 是否需不变等需求决定。</p>
<p class="maodian"><a name="_label1"></a></p><h2>2. 删</h2>
<p class="maodian"><a name="_lab2_1_6"></a></p><h3>2.1 删除表(delete)</h3>
<p>语法:</p>
<div class="jb51code"><pre class="brush:sql;">DELETE FROM table_name </pre></div>
<p>我们来看下面这行代码,我们可以通过delete这个指令来删除表中的一行。</p>
<p>如果我们把WHERE name = &#39;孙悟空&#39;;这句话去掉的话,那么delete就会直接删除掉整张表。</p>
<div class="jb51code"><pre class="brush:sql;">-- 查看原数据 SELECT * FROM exam_result WHERE name = '孙悟空';
+----+-----------+-------+--------+--------+
| id | name | chinese | math | english |
+----+-----------+-------+--------+--------+
| 2 | 孙悟空 | 174 | 80 | 77 | +
----+-----------+-------+--------+--------+
1 row in set (0.00 sec)
-- 删除数据
DELETE FROM exam_result WHERE name = '孙悟空';
Query OK, 1 row affected (0.17 sec)
-- 查看删除结果
SELECT * FROM exam_result WHERE name = '孙悟空';
Empty set (0.00 sec)</pre></div>
<p>PS:delete是不会让那个auto_increment重新开始计算的,也就是说我们删除一张表之后如果再往里面插入数据的话,</p>
<p class="maodian"><a name="_lab2_1_7"></a></p><h3>2.2 截断表(truncate)</h3>
<p>语法:</p>
<div class="jb51code"><pre class="brush:sql;">TRUNCATE table_name</pre></div>
<p><strong><span>注意:这个操作慎用 </span></strong></p>
<p><span>1. </span><span>只能对整表操作,不能像</span><span> DELETE </span><span>一样针对部分数据操作; </span></p>
<p><span>2. </span><span>实际上</span><span> MySQL </span><span>不对数据操作,所以比</span><span> DELETE </span><span>更快,但是</span><span>TRUNCATE</span><span>在删除数据的时候,并不经过真正的事物,所以无法回滚 </span></p>
<p><span>3. </span><span>会重置</span><span> AUTO_INCREMENT </span><span>项 </span></p>
<p><span>所以说这个的话就仅做了解即可,因为他不支持数据回滚就意味着无法通过一些常规手段来对数据表进行复原。但是他删除数据的速度很快,在一些已经确定要删除且数据很大的表中很好用。</span></p>
<p class="maodian"><a name="_lab2_1_8"></a></p><h3>2.3 删除的注意点</h3>
<p><code>DELETE</code>&nbsp;和&nbsp;<code>TRUNCATE</code>&nbsp;都只删除表中的<strong>数据</strong>,而<strong>表的结构(包括列定义、数据类型、索引、约束、主键等)会被完整保留</strong>,不会被删除。</p>
<p>具体来说:</p>
<ul><li><code>delete</code>:仅删除表中符合条件的行(或全表行),表的结构、索引、约束等元数据完全不变。</li><li>truncate:同样只删除数据,表的结构、索引、约束等依然保留(相当于 &ldquo;清空内容但保留容器&rdquo;)。</li></ul>
頁: [1]
查看完整版本: 如何在SQL中实现表的增删