SQL 插入数据详解

devtools/2024/12/22 8:47:34/

本文介绍如何利用 SQL 的 INSERT 语句将数据插入表中。

1. 数据插入

顾名思义,INSERT 用来将行插入(或添加)到数据库表。插入有几种方式:

  • 插入完整的行;
  • 插入行的一部分;
  • 插入某些查询的结果。

下面逐一介绍这些内容。

1.1 插入完整的行

把数据插入表中的最简单方法是使用基本的 INSERT 语法,它要求指定表名和插入到新行中的值。下面举一个例子:

sql">INSERT INTO Customers
VALUES(1000000006,
'Toy Land',
'123 Any Street',
'New York',
'NY',
'11111',
'USA',
NULL,
NULL);

分析:这个例子将一个新顾客插入到 Customers 表中。存储到表中每一列的数据在 VALUES 子句中给出,必须给每一列提供一个值。如果某列没有值,如上面的 cust_contactcust_email 列,则应该使用 NULL 值(假定表允许对该列指定空值)。各列必须以它们在表定义中出现的次序填充。

提示:INTO 关键字

在某些 SQL 实现中,跟在 INSERT 之后的 INTO 关键字是可选的。但是,即使不一定需要,最好还是提供这个关键字,这样做将保证 SQL 代码在 DBMS 之间可移植。

虽然这种语法很简单,但并不安全,应该尽量避免使用。上面的 SQL 语句高度依赖于表中列的定义次序,还依赖于其容易获得的次序信息。即使可以得到这种次序信息,也不能保证各列在下一次表结构变动后保持完全相同的次序。因此,编写依赖于特定列次序的 SQL 语句是很不安全的,这样做迟早会出问题。

编写 INSERT 语句的更安全(不过更烦琐)的方法如下:

sql">INSERT INTO Customers(cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country,
cust_contact,
cust_email)
VALUES(1000000006,
'Toy Land',
'123 Any Street',
'New York',
'NY',
'11111',
'USA',
NULL,
NULL);

分析:这个例子与前一个 INSERT 语句的工作完全相同,但在表名后的括号里明确给出了列名。在插入行时,DBMS 将用 VALUES 列表中的相应值填入列表中的对应项。VALUES 中的第一个值对应于第一个指定列名,第二个值对应于第二个列名,如此等等。

因为提供了列名,VALUES 必须以其指定的次序匹配指定的列名,不一定按各列出现在表中的实际次序。其优点是,即使表的结构改变,这条 INSERT 语句仍然能正确工作。

说明:不能插入同一条记录两次

如果你尝试了这个例子的两种方法,会发现第二次生成了一条出错消息,说 ID 为 1000000006 的顾客已经存在。在第一课我们说过,主键的值必须有唯一性,而 cust_id 是主键,DBMS 不允许插入相同 cust_id 值的新行。

下面的 INSERT 语句填充所有列(与前面的一样),但以一种不同的次序填充。因为给出了列名,所以插入结果仍然正确:

sql">INSERT INTO Customers(cust_id,
cust_contact,
cust_email,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip)
VALUES(1000000006,
NULL,
NULL,
'Toy Land',
'123 Any Street',
'New York',
'NY',
'11111');

提示:总是使用列的列表

不要使用没有明确给出列的 INSERT 语句。给出列能使 SQL 代码继续发挥作用,即使表结构发生了变化。

注意:小心使用 VALUES

不管使用哪种 INSERT 语法,VALUES 的数目都必须正确。如果不提供列名,则必须给每个表列提供一个值;如果提供列名,则必须给列出的每个列一个值。否则,就会产生一条错误消息,相应的行不能成功插入。

1.2 插入部分行

正如所述,使用 INSERT 的推荐方法是明确给出表的列名。使用这种语法,还可以省略列,这表示可以只给某些列提供值,给其他列不提供值。

请看下面的例子:

sql">INSERT INTO Customers(cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country)
VALUES(1000000006,
'Toy Land',
'123 Any Street',
'New York',
'NY',
'11111',
'USA');

分析:在前面的例子中,没有给 cust_contactcust_email 这两列提供值。这表示没必要在 INSERT 语句中包含它们。因此,这里的 INSERT 语句省略了这两列及其对应的值。

注意:省略列

如果表的定义允许,则可以在 INSERT 操作中省略某些列。省略的列必须满足以下某个条件:

  1. 该列定义为允许 NULL 值(无值或空值)。
  2. 在表定义中给出默认值。这表示如果不给出值,将使用默认值。

注意:省略所需的值

如果表中不允许有 NULL 值或者默认值,这时却省略了表中的值,DBMS 就会产生错误消息,相应的行不能成功插入。

1.3 插入检索出的数据

INSERT 一般用来给表插入具有指定列值的行。INSERT 还存在另一种形式,可以利用它将 SELECT 语句的结果插入表中,这就是所谓的 INSERT SELECT。顾名思义,它是由一条 INSERT 语句和一条 SELECT 语句组成的。

假如想把另一表中的顾客列合并到 Customers 表中,不需要每次读取一行再将它用 INSERT 插入,可以如下进行:

sql">INSERT INTO Customers(cust_id,
cust_contact,
cust_email,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country)
SELECT cust_id,
cust_contact,
cust_email,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country
FROM CustNew;

说明:新例子的说明

这个例子从一个名为 CustNew 的表中读出数据并插入到 Customers 表。为了试验这个例子,应该首先创建和填充 CustNew 表。CustNew 表的结构与 Customers 表相同。在填充 CustNew 时,不应该使用已经在 Customers 中用过的 cust_id 值(如果主键值重复,后续的 INSERT 操作将会失败)。

分析:这个例子使用 INSERT SELECTCustNew 中将所有数据导入 CustomersSELECT 语句从 CustNew 检索出要插入的值,而不是列出它们。SELECT 中列出的每一列对应于 Customers 表名后所跟的每一列。这条语句将插入多少行呢?这依赖于 CustNew 表有多少行。如果这个表为空,则没有行被插入(也不产生错误,因为操作仍然是合法的)。如果这个表确实有数据,则所有数据将被插入到 Customers

提示:INSERT SELECT 中的列名

为简单起见,这个例子在 INSERTSELECT 语句中使用了相同的列名。但是,不一定要求列名匹配。事实上,DBMS 一点儿也不关心 SELECT 返回的列名。它使用的是列的位置,因此 SELECT 中的第一列(不管其列名)将用来填充表列中指定的第一列,第二列将用来填充表列中指定的第二列,如此等等。

INSERT SELECTSELECT 语句可以包含 WHERE 子句,以过滤插入的数据。

提示:插入多行

INSERT 通常只插入一行。要插入多行,必须执行多个 INSERT 语句。INSERT SELECT 是个例外,它可以用一条 INSERT 插入多行,不管 SELECT 语句返回多少行,都将被 INSERT 插入。

2. 从一个表复制到另一个表

有一种数据插入不使用 INSERT 语句。要将一个表的内容复制到一个全新的表(运行中创建的表),可以使用 CREATE SELECT 语句(或者在 SQL Server 里也可用 SELECT INTO 语句)。

说明:DB2 不支持

DB2 不支持这里描述的 CREATE SELECT

INSERT SELECT 将数据添加到一个已经存在的表不同,CREATE SELECT 将数据复制到一个新表(有的 DBMS 可以覆盖已经存在的表,这依赖于所使用的具体 DBMS)。

下面的例子说明如何使用 CREATE SELECT

sql">CREATE TABLE CustCopy AS SELECT * FROM Customers;

若是使用 SQL Server,可以这么写:

sql">SELECT * INTO CustCopy FROM Customers;

分析:这条 SELECT 语句创建一个名为 CustCopy 的新表,并把 Customers 表的整个内容复制到新表中。因为这里使用的是 SELECT *,所以将在 CustCopy 表中创建(并填充)与 Customers 表相同的列结构。

3. 插入数据时的注意事项

插入数据时有几个常见的注意点:

  1. 数据类型匹配: 在使用 INSERT 语句时,确保插入的数据与目标表的列的数据类型匹配。例如,如果某个列定义为 INT 类型,你不能尝试插入一个字符串值。

  2. 约束条件: 如果目标表的列有约束条件(如 NOT NULLUNIQUEPRIMARY KEY),插入数据时需要确保这些约束得到满足,否则会导致插入失败。

  3. 默认值与 NULL: 如果某些列允许 NULL 或有默认值,你可以选择不插入值,DBMS 将自动填充 NULL 或默认值。如果列没有设置默认值且不允许 NULL,插入时必须提供值。

  4. 避免重复数据: 在插入数据时,要特别注意主键的唯一性。如果尝试插入一条具有相同主键的记录,将会出现错误。在插入前,可以使用查询检查主键值是否已存在。

  5. 批量插入: 在某些情况下,需要批量插入数据。可以使用多行 INSERT 语句来一次性插入多条记录。例如:

    sql">INSERT INTO Customers (cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country)
    VALUES
    (1000000007, 'Toy Factory', '456 Some Street', 'Los Angeles', 'CA', '90001', 'USA'),
    (1000000008, 'Tech Zone', '789 Tech Road', 'San Francisco', 'CA', '94105', 'USA'),
    (1000000009, 'Book World', '101 Book Lane', 'Chicago', 'IL', '60601', 'USA');
  6. 事务处理: 如果你执行多个插入操作,并且这些操作之间有依赖关系,可以将它们放在一个事务中,确保数据一致性。如果在插入过程中出现错误,事务可以回滚,从而避免部分插入成功导致数据不一致的情况。


4. 总结

INSERT 语句是 SQL 中用来向表中插入数据的基础工具,理解和掌握不同的插入方式对于有效地管理数据库至关重要。插入数据时应注意以下几点:

  • 明确指定列名和插入顺序,以确保插入数据的安全性。
  • 小心处理 NULL 和默认值。
  • 使用 INSERT SELECT 语法插入来自其他表的数据。
  • 在批量插入数据时,要确保数据的一致性和完整性。
  • 通过事务控制确保插入操作的原子性。

了解这些插入数据的基本操作和注意事项,能够帮助你更高效地进行数据库的管理与维护。


http://www.ppmy.cn/devtools/144324.html

相关文章

QT实战经验总结 连载中

QT实战经验总结 在看书系统学习后,就开始实战了,会遇到很多问题1.信号和槽的思考2.在python 或 C 代码中,对 QML 代码中控件的调用3.关于在一个窗口上不断打开新窗口 在看书系统学习后,就开始实战了,会遇到很多问题 p…

Apache 如何监听多个端口 ?

Apache 是一个广泛使用的 web 服务器,可以配置为侦听多个端口。这对于托管多个网站、运行不同类型的服务或改进服务器的可访问性特别有用。在本文中,我们将探讨配置 Apache 以侦听多个端口的步骤。 Step 1: Access Apache Configuration File 找到并打…

uboot 打开log 的 方法

uboot 版本 commit f919c3a889f0ec7d63a48b5d0ed064386b0980bd (HEAD -> v2024.10, tag: v2024.10) Author: Tom Rini <trinikonsulko.com> Date: Mon Oct 7 08:54:35 2024 -0600 Prepare v2024.10 Signed-off-by: Tom Rini <trinikonsulko.com> 开启的选项…

Vue2/3 生命周期详细对比与使用指南

Vue 2 生命周期 Vue 2 中,生命周期是指组件实例在创建、挂载、更新、销毁时所经历的一系列过程。以下是 Vue 2 的生命周期图和主要钩子函数的描述: Vue 2 生命周期钩子 beforeCreate:实例初始化之后调用,数据观测和事件配置尚未完成。常用于初始化逻辑。created:实例创建…

文件防泄漏 | 文件防泄漏软件解决方案分享,网络数据泄露防护系统

文件防泄漏 | 文件防泄漏软件解决方案分享&#xff0c;网络数据泄露防护系统 企业面临的一大挑战是数据安全和隐私保护。 网络数据泄露不仅会导致经济损失&#xff0c;还会损害企业的声誉和客户关系。 为了应对这一挑战&#xff0c;域智盾软件应运而生&#xff0c;成为众多企…

【Flutter_Web】Flutter编译Web第二篇(webview篇):flutter_inappwebview如何改造方法,变成web之后数据如何交互

前言 欢迎来到第二篇文章&#xff0c;这也是第二个难题&#xff0c;就是原有的移动端本身一些页面H5的形式去呈现&#xff08;webview&#xff09;&#xff0c;例如某些需要动态更换内容的页面&#xff0c;某些活动页面、支付页面&#xff0c;不仅仅做页面呈现&#xff0c;还包…

2024年11月 蓝桥杯青少组 STEMA考试 Scratch真题

2024年11月 蓝桥杯青少组 STEMA考试 Scratch真题&#xff08;选择题&#xff09; 题目总数&#xff1a;5 总分数&#xff1a;50 选择题 第 1 题 单选题 Scratch运行以下程宇后&#xff0c;小兔子会&#xff08; &#xff09;。 A. 变小 B. 变大 C. 变色 D. …

在 .NET 5.0 运行 .NET 8.0 教程:使用 ASP.NET Core 创建 Web API

前言 因为我本机安装的是vs2019&#xff0c;所以我在使用vs创建项目的时候&#xff0c;只能选择.NET 5.0&#xff0c;而无法选择.NET 8.0 在网上有看到说用vs2019使用.net 8.0 &#xff0c;但是感觉不可靠&#xff0c;要用还是安装vs2022吧。 我因为不想要安装vs2022。 但是微…