【SQL INSERT入门】如何使用INSERT INTO语句向表中添加新数据
网站的用户注册、博客的新帖子、电商网站的商品上架……Web应用之所以充满活力,正是因为新数据在源源不断地产生。而承担“向数据库注册新数据”这一最基本、最重要操作的,就是SQL的INSERT语句。
INSERT语句是向数据库这个巨大的账本中写入新行的命令。它的语法乍一看很简单,但用法却多种多样,从只添加一行,到批量注册多行,再到从其他表复制数据。然而,正因为简单,一点小错误就容易导致失败,也成为初学者容易卡壳的地方。
本文旨在帮助Web开发者们完全掌握INSERT语句。我们将通过大量“即拷即用”的代码,从基本写法到实际应用,再到常见错误及其处理方法,进行全面而详尽的解说。让我们先动手运行代码,感受“数据被成功添加!”的喜悦,以此迈出踏入SQL世界的第一步吧。
准备工作:创建一个用于添加数据的表
要添加数据,首先需要一个存放数据的“盒子”,也就是表。这次,我们来创建一个名为products的表,用于管理新商品的信息。在整篇文章中,我们都将使用这个表。
值得注意的是id列的INTEGER PRIMARY KEY。在许多数据库中(如SQLite,或MySQL中的AUTO_INCREMENT),这样设置后,每次添加数据时,系统都会自动分配一个唯一的ID。这一点在后面会非常重要。
-- 如果products表已存在,则删除(以便重复测试)
DROP TABLE IF EXISTS products;
-- 创建一个新的products表
CREATE TABLE products (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
category TEXT,
price INTEGER,
release_date DATE
);
这样,一个用于注册商品数据的空表就准备好了。接下来,让我们立刻为这个表注入新的生命力吧。
【基础】INSERT INTO ... VALUES: 添加单行数据
首先是INSERT语句的基本形式:“添加单行数据”的方法。语法是INSERT INTO 表名 (列1, 列2, ...) VALUES (值1, 值2, ...);。重点在于,第一个括号内的列列表与VALUES后的值列表要按顺序一一对应。
INSERT INTO products (name, category, price, release_date)
VALUES ('奇迹苹果', '食品', 500, '2025-07-01');
执行此查询后,products表中会添加一条新商品记录。我们没有指定id列,但由于在创建表时设置了自动编号,数据库会自动为其分配ID1。这是将主键(PRIMARY KEY)设置为自动递增的一大优点。
让我们来确认一下是否添加成功。执行SELECT * FROM products;,应该就能看到刚才添加的数据。
SELECT * FROM products;
执行结果:
id | name | category | price | release_date
---|----------|----------|-------|-------------
1 | 奇迹苹果 | 食品 | 500 | 2025-07-01
另外,如果某些列的值尚未确定(仅限于允许NULL的列),可以在插入时省略这些列。
-- 插入时省略价格(price)和发布日期(release_date)
INSERT INTO products (name, category)
VALUES ('梦幻桃子', '食品');
在这种情况下,price和release_date列将包含NULL(无值)。
【应用1】一次性批量添加多行数据
逐一注册新商品有点麻烦。INSERT语句支持在一次查询中批量添加多条数据。
写法很简单,只需在VALUES关键字后,用逗号(,)分隔多个由()包裹的值列表即可。这样可以减少与数据库的通信次数,比逐行重复执行INSERT语句效率更高。
INSERT INTO products (name, category, price, release_date) VALUES
('魔法键盘', '数码产品', 12000, '2025-07-10'),
('彩虹鼠标', '数码产品', 5000, '2025-07-20'),
('天空葡萄', '食品', 2500, '2025-08-01');
通过这一条查询,三条商品数据就被一次性添加进去了。在投入初始数据或批量注册从CSV文件读取的数据时,这是一个非常方便的技巧。
【应用2】使用`INSERT ... SELECT`语句从其他表复制数据
这是一个面向中级用户且非常强大的技巧。使用INSERT ... SELECT语句,你可以将从另一个表中用SELECT语句查询出的结果,直接添加到新表中。
例如,在“将‘新品到货列表’表(new_arrivals)中已确定发售的商品移至products表”这样的场景中,它能大显身手。
首先,让我们创建作为复制源的new_arrivals表,并注册一些数据。
-- 创建源表
CREATE TABLE new_arrivals (
product_name TEXT NOT NULL,
product_category TEXT,
list_price INTEGER,
launch_date DATE,
is_confirmed INTEGER -- 如果确定发售则为1,否则为0
);
-- 在新品到货列表中注册数据
INSERT INTO new_arrivals VALUES
('终极耳机', '音频设备', 28000, '2025-09-01', 1),
('未来VR眼镜', '数码产品', 75000, '2025-10-01', 1),
('全自动咖啡机', '家电', 18000, '2025-09-15', 0);
准备好了。现在,让我们从new_arrivals表中选出已确定发售(is_confirmed = 1)的商品,并将其添加到products表中。
INSERT INTO products (name, category, price, release_date)
SELECT product_name, product_category, list_price, launch_date
FROM new_arrivals
WHERE is_confirmed = 1;
此查询的重点是使用SELECT语句代替了VALUES子句。SELECT语句检索的列结构(列的数量、顺序、数据类型)必须与INSERT INTO products (...)中指定的列结构相匹配。这种方法的用途非常广泛,例如数据备份、将聚合结果保存到另一张表等。
初学者常遇到的INSERT语句错误及处理方法
如果违反了数据库的规则(约束),INSERT语句会立即返回错误。在这里,我们来看看初学者常遇到的典型错误、其原因及处理方法。
错误1:主键(PRIMARY KEY)重复
这是最常见的错误。主键是表内绝不能重复的唯一标识符。如果你手动指定ID,并试图再次使用一个已经存在的ID,就会发生错误。
例如,ID=1的“奇迹苹果”已经注册。如果我们再次尝试用ID=1注册一个新商品……
-- 这会导致错误!
INSERT INTO products (id, name, category, price, release_date)
VALUES (1, '另一个苹果', '食品', 300, '2025-07-02');
执行此操作将显示类似UNIQUE constraint failed: products.id或Duplicate entry '1' for key 'PRIMARY'的错误消息。
处理方法: 最安全可靠的方法是不要手动管理主键,而是交给数据库的自动编号功能。就像第一个例子那样,在INSERT语句的列列表中不包含id即可。
错误2:违反NOT NULL约束
在创建表时指定为NOT NULL的列必须有值。如果尝试插入时省略了该列,就会发生错误。
products表的name列是NOT NULL。如果我们尝试在不指定name的情况下插入……
-- 这也会导致错误!
INSERT INTO products (category, price)
VALUES ('其他', 1000);
将会显示类似NOT NULL constraint failed: products.name的错误。
处理方法: 对于有NOT NULL约束的列,务必指定某个值。如果希望允许空字符串,则需明确指定为''。
错误3:数据类型不匹配
如果你尝试插入与表定义中规定的数据类型不符的数据,就会发生错误。例如,尝试将字符串插入到数值类型(INTEGER)的price列中。
-- 这当然也会导致错误!
INSERT INTO products (name, price)
VALUES ('昂贵的石头', '价格是秘密');
将会出现类似Datatype mismatch或Incorrect integer value: '价格是秘密' for column 'price'的错误。
处理方法: 仔细检查表定义,并为每列指定正确数据类型的值。请注意,将数字用引号括起来(如'500')使其变为字符串也是一个常见错误。
【体验环节】在浏览器中运行SQL,添加数据吧!
现在,是时候将知识转化为技能了!将下面的HTML代码完整复制,保存为sql_insert_test.html之类的文件名,然后在浏览器中打开它。你专属的SQL执行环境将会启动,并且本文中创建的products表已经为你准备好了。
你可以自由地编写INSERT语句并点击“执行”按钮,然后在下面紧接着编写SELECT * FROM products;并再次“执行”,来确认数据是否真的被添加了。故意制造一些错误也是很好的学习方式哦!
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SQL INSERT语句 在线执行环境</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.7; color: #333; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
h1 { color: #2c3e50; }
textarea { width: 100%; height: 180px; font-family: "SF Mono", "Consolas", monospace; font-size: 16px; padding: 12px; border: 1px solid #ccc; border-radius: 6px; box-sizing: border-box; margin-bottom: 1rem; }
button { background-color: #27ae60; color: white; border: none; padding: 12px 22px; font-size: 16px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; }
button:hover { background-color: #229954; }
button:disabled { background-color: #bdc3c7; cursor: not-allowed; }
#result-container { margin-top: 2rem; border: 1px solid #ddd; padding: 1rem; border-radius: 6px; background: #fdfdfd; min-height: 50px; }
#status-message { color: #27ae60; font-weight: bold; }
#error-message { color: #e74c3c; font-weight: bold; }
table { border-collapse: collapse; width: 100%; margin-top: 1rem; }
th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
th { background-color: #f2f2f2; }
tr:nth-child(even) { background-color: #f9f9f9; }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.js"></script>
</head>
<body>
<h1>来试试SQL吧!</h1>
<p>在下面的文本框中输入SQL语句,然后点击“执行”按钮。试试插入一个你自己想出来的商品吧!</p>
<textarea id="sql-input">-- 在这里写下你的INSERT或SELECT语句
INSERT INTO products (name, category, price, release_date)
VALUES ('无重力椅', '家具', 45000, '2025-11-11');
SELECT * FROM products;
</textarea>
<button id="execute-btn">执行</button>
<div id="result-container">
<p id="status-message"></p>
<p id="error-message"></p>
<div id="result-output"></div>
</div>
<script>
const sqlInput = document.getElementById('sql-input');
const executeBtn = document.getElementById('execute-btn');
const statusMsg = document.getElementById('status-message');
const errorMsg = document.getElementById('error-message');
const resultOutput = document.getElementById('result-output');
let db;
async function initDb() {
executeBtn.disabled = true;
executeBtn.textContent = '数据库准备中...';
try {
const SQL = await initSqlJs({
locateFile: file => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/${file}`
});
db = new SQL.Database();
const setupSql = `
DROP TABLE IF EXISTS products;
CREATE TABLE products (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
category TEXT,
price INTEGER,
release_date DATE
);
`;
db.run(setupSql);
executeBtn.disabled = false;
executeBtn.textContent = '执行';
statusMsg.textContent = '准备就绪!请尝试用INSERT语句添加数据,并用SELECT语句确认结果。';
} catch (err) {
errorMsg.textContent = '数据库初始化失败:' + err.message;
console.error(err);
}
}
function executeSql() {
if (!db) return;
const sql = sqlInput.value;
statusMsg.textContent = '';
errorMsg.textContent = '';
resultOutput.innerHTML = '';
try {
const statements = sql.split(';').filter(s => s.trim() !== '');
let lastResult;
statements.forEach(stmt => {
const trimmedStmt = stmt.trim();
if (trimmedStmt.toUpperCase().startsWith('INSERT') || trimmedStmt.toUpperCase().startsWith('UPDATE') || trimmedStmt.toUpperCase().startsWith('DELETE')) {
db.run(trimmedStmt);
const changes = db.getRowsModified();
statusMsg.innerHTML += `查询 “${trimmedStmt.substring(0, 30)}...” 已执行,${changes}行受到影响。<br>`;
} else {
const results = db.exec(trimmedStmt);
lastResult = results;
}
});
if (lastResult && lastResult.length > 0) {
lastResult.forEach(result => {
const table = document.createElement('table');
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');
const headerRow = document.createElement('tr');
result.columns.forEach(colName => {
const th = document.createElement('th');
th.textContent = colName;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
result.values.forEach(row => {
const bodyRow = document.createElement('tr');
row.forEach(cellValue => {
const td = document.createElement('td');
td.textContent = cellValue === null ? 'NULL' : cellValue;
bodyRow.appendChild(td);
});
tbody.appendChild(bodyRow);
});
table.appendChild(thead);
table.appendChild(tbody);
resultOutput.appendChild(table);
});
}
} catch (err) {
errorMsg.textContent = 'SQL错误:' + err.message;
console.error(err);
}
}
executeBtn.addEventListener('click', executeSql);
initDb();
</script>
</body>
</html>
INSERT的伙伴们:CRUD操作
学会了INSERT,你就掌握了数据库操作基本四项能力中的一项。这四项操作的首字母缩写被称为CRUD,是所有应用程序数据操作的基础。
- C (Create - 创建): 创建新数据 →
INSERT语句(我们今天学习的!) - R (Read - 读取): 读取数据 →
SELECT语句 - U (Update - 更新): 更新现有数据 →
UPDATE语句 - D (Delete - 删除): 删除现有数据 →
DELETE语句
你已经对SELECT很熟悉了。现在你已经可以“添加”数据,下一步可以学习如何“更新”(UPDATE)或“删除”(DELETE)数据,这将进一步拓宽你能用数据库做的事情的范围。
总结
这次,我们详细学习了用于向数据库添加新数据的INSERT语句,内容涵盖了从基础到应用,再到需要注意的错误。
- 基本语法:
INSERT INTO 表 (列...) VALUES (值...);是所有操作的基础。 - 主键: 设置为自动编号,把ID管理交给数据库,既安全又可靠。
- 多行INSERT: 在
VALUES子句后用逗号连接多个值列表,可以实现批量注册。 - INSERT SELECT: 可以将从其他表查询到的数据完整添加进来,是一个强大的技巧。
- 错误处理: “主键重复”、“NOT NULL冲突”、“数据类型不匹配”是三大常见错误。理解了原因就没什么好怕的了。
INSERT语句是为你的网站和应用注入生命、记录用户行为、丰富内容的第一步。请在本文的体验环节中反复练习,掌握自由自在地添加数据的感觉。这些微小成功经验的积累,必将引导你成为一名顶尖的Web开发者。