前面主要使用 SELECT 读取数据,但真实系统也要不断创建记录:用户注册时保存用户,管理员上架商品时写入 products。SQL 最常用 INSERT INTO 添加 Row。
下面的语句分成两部分:第一部分指定目标 Table 和接收值的 Column;第二部分提供相同顺序的 VALUES。执行后,再查询 users 就会看到 Emma 成为新的 Row。
INSERT INTO users (id, name, email, city)
VALUES (5, 'Emma', '[email protected]', 'Nagoya');Column 与 Value 必须一一对应
(name, email, city) 对应 ('Emma', '[email protected]', 'Nagoya')。如果把 Nagoya 和邮箱交换,数据库不会猜测本意,只会按位置保存。数据类型冲突可能让语句失败;若类型恰好兼容,错误数据甚至会真的写入。
为什么有时不填写 id?
真实项目经常让数据库自动生成主键 id。MySQL、PostgreSQL 和 SQL Server 的具体机制不同,但共同思路是应用只提供业务数据,数据库分配唯一编号。
| Column 位置 | name | email | city |
|---|---|---|---|
| 对应 Value | Emma | [email protected] | Nagoya |
可以只填写部分字段
允许 NULL 或拥有 DEFAULT 的 Column 可以省略。例如只提供 name 和 email 时,city 可能成为 NULL 或使用默认值。若 Column 是 NOT NULL 且没有默认值,INSERT 会失败。写入是否有效取决于 SQL 和 Table 规则。
一次添加多条 Row
许多数据库允许一次提供多组 VALUES。它适合准备测试数据或导入小批记录,通常也比连续执行多条 INSERT 更清晰。先理解单行中的对应关系,多行只是重复相同结构。
INSERT INTO users (name, email, city)
VALUES
('Emma', '[email protected]', 'Nagoya'),
('Frank', '[email protected]', 'Tokyo'),
('Grace', '[email protected]', 'Osaka');字符串、数字与日期
字符串通常使用单引号,数字不加引号。订单中的 user_id、product_id 和 quantity 是数字,order_date 可使用直观的 YYYY-MM-DD 日期字符串;不同产品在日期细节上可能有差异。
写入后查询确认
INSERT 后立即用 SELECT 检查是很实用的习惯。它可以发现字段顺序错误、值不正确或语句没有成功。与只生成 Result Set 的 SELECT 不同,INSERT 会真正改变 Table,所以写入生产数据库前要确认 Database、Table 和内容。
| 语句 | 作用 | 是否改变 Table |
|---|---|---|
SELECT | 读取数据 | 否 |
INSERT | 创建新 Row | 是 |
向 Table 写入一条或多条 Row
运行 INSERT 后,新 Row 会真实出现在模拟表中;省略 id 时沙盒会自动分配编号。
| id | name | city | |
|---|---|---|---|
| 1 | Alice | [email protected] | Tokyo |
| 2 | Bob | [email protected] | Osaka |
| 3 | Chris | [email protected] | Tokyo |
| 4 | Diana | [email protected] | Kyoto |
沙盒已准备好,不会连接真实数据库。知识测验
单行与多行 INSERT
完成两项任务:
① 向 products 添加 Webcam,价格 55.00,类别 Electronics;
② 用一条 INSERT 向 users 添加 Helen(Sapporo)和 Ian(Tokyo)。省略自动生成的 id,并为用户提供合理的邮箱。验收标准:字符串有单引号、数字无引号、多行 VALUES 用逗号分隔。
可选:通用练习表
DROP TABLE IF EXISTS products;
DROP TABLE IF EXISTS users;
CREATE TABLE users (id INTEGER, name VARCHAR(100), email VARCHAR(200), city VARCHAR(100));
CREATE TABLE products (id INTEGER, name VARCHAR(100), price DECIMAL(10,2), category VARCHAR(50));