
插入数据
INSERT INTO … VALUES …
INSERT INTO … SELECT …
插入单行记录
INSERT INTO t(col1, col2, ...)
VALUES (value1, value2, ...);
INSERT INTO employee (emp_name, sex, dept_id, manager, hire_date,
job_id, salary, bonus, email, comments,
create_by, create_ts, update_by, update_ts)
VALUES ('张三', '男', 5, 18, CURRENT_DATE, -- Microsoft SQL Server 需要替换该函数
10, 6000, NULL, 'zhangsan@shuguo.com', NULL,
'Admin', CURRENT_TIMESTAMP, NULL, NULL);
-- Oracle 需要执行以下COMMIT 语句
-- COMMIT;
SELECT emp_id, emp_name, sex
FROM employee
WHERE emp_name = '张三';
emp_id|emp_name|sex
------|--------|---
26| 张三 |男
-- Oracle
SQL 错误 [1] [23000]: ORA-00001: 违反唯一约束条件 (TONY.UK_EMP_EMAIL)
-- MySQL
SQL 错 误 [1062] [23000]: Duplicate entry 'zhangsan@shuguo.com' for key
'employee.uk_emp_email'
-- Microsoft SQL Server
SQL 错误 [2627] [23000]: 违反了 UNIQUE KEY 约束“uk_emp_email ”。不能在对象
“dbo.employee”中插入重复键。重复键值为 (zhangsan@shuguo.com)。
-- PostgreSQL
SQL 错误 [23505]: 错误: 重复键违反唯一约束"uk_emp_email"
详细:键值"(email)=(zhangsan@shuguo.com)" 已经存在
-- SQLite
SQL 错误 [19]: [SQLITE_CONSTRAINT] Abort due to constraint violation (UNIQUE
constraint failed: employee.email)
-- 违反非空约束,sex 字段不能为空
INSERT INTO employee (emp_name)
VALUES('张三');
-- 违反检查约束,salary 必须大于0
INSERT INTO employee (emp_name, sex, dept_id, manager, hire_date,
job_id, salary, bonus, email, comments,
create_by, create_ts, update_by, update_ts)
VALUES ('李四', '女', 5, 18, CURRENT_DATE, -- Microsoft SQL Server 需要替换该函数
10, 0, NULL, 'lisi@shuguo.com', NULL,
'Admin', CURRENT_TIMESTAMP, NULL, NULL);
CREATE TABLE t_default(
id INTEGER,
c INTEGER DEFAULT 100
);
INSERT INTO t_default VALUES (1, DEFAULT);
SELECT * FROM t_default;
id|c
--|---
1|100
插入多行记录
INSERT INTO employee (emp_name, sex, dept_id, manager, hire_date,
job_id, salary, bonus, email, comments,
create_by, create_ts, update_by, update_ts)
VALUES ('李四', '女', 5, 18, '2021-06-06',
10, 6000, NULL, 'lisi@shuguo.com', NULL,
'Admin', CURRENT_TIMESTAMP, NULL, NULL),
('王五', '男', 5, 18, '2021-06-06',
10, 6000, NULL, 'lisi@shuguo.com', NULL,
'Admin', CURRENT_TIMESTAMP, NULL, NULL),
('赵六', '女', 5, 18, '2021-06-06',
10, 6000, NULL, 'lisi@shuguo.com', NULL,
'Admin', CURRENT_TIMESTAMP, NULL, NULL);
复制数据
CREATE TABLE emp_devp
( emp_id INTEGER NOT NULL PRIMARY KEY
, emp_name VARCHAR(50) NOT NULL
, sex VARCHAR(10) NOT NULL
, dept_id INTEGER NOT NULL
, manager INTEGER
, hire_date DATE NOT NULL
, job_id INTEGER NOT NULL
, salary NUMERIC(8,2) NOT NULL
, bonus NUMERIC(8,2)
, email VARCHAR(100) NOT NULL
);
INSERT INTO emp_devp(emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email)
SELECT e.emp_id, e.emp_name, e.sex, e.dept_id, e.manager,
e.hire_date, e.job_id, e.salary, e.bonus, e.email
FROM employee e
JOIN department d ON (d.dept_id = e.dept_id)
WHERE dept_name = '研发部';
SELECT COUNT(*)
FROM emp_devp;
COUNT(*)
--------
9
更新数据
单表更新
UPDATE t
SET col1 = expr1,
col2 = expr2,
...
[WHERE condition];
UPDATE emp_devp
SET salary = salary + 1000,
bonus = 8000
WHERE emp_name = '赵云';
SELECT emp_name AS "姓名", salary AS "月薪", bonus AS "奖金"
FROM emp_devp
WHERE emp_name = '赵云';
姓名|月薪 |奖金
---|--------|-------
赵云|16000.00|8000.00
关联更新
-- Oracle、PostgreSQL 以及SQLite
UPDATE emp_devp
SET (salary, bonus, email) = (SELECT salary, bonus, email
FROM employee e
WHERE e.emp_id = emp_devp.emp_id);
-- MySQL
UPDATE emp_devp ed
JOIN employee e ON (e.emp_id = ed.emp_id)
SET ed.salary = e.salary,
ed.bonus = e.bonus,
ed.email = e.email;
-- Microsoft SQL Server
UPDATE emp_devp
SET salary = e.salary,
bonus = e.bonus,
email = e.email
FROM emp_devp ed
JOIN employee e ON (e.emp_id = ed.emp_id);
-- Oracle 23c、PostgreSQL、SQLite
UPDATE emp_devp AS ed
SET salary = e.salary,
bonus = e.bonus,
email = e.email
FROM employee e
WHERE e.emp_id = ed.emp_id;
删除数据
单表删除
DELETE FROM t
[WHERE conditions];
-- SELECT *
DELETE
FROM employee
WHERE emp_name IN ('张三', '李四', '王五', '赵六');
关联删除
-- SELECT *
DELETE
FROM emp_devp
WHERE emp_id IN (SELECT emp_id FROM employee);
-- MySQL
DELETE ed
FROM emp_devp ed
JOIN employee e ON (ed.emp_id = e.emp_id);
-- Oracle 23c、PostgreSQL
DELETE
FROM emp_devp ed
USING employee e
WHERE ed.emp_id = e.emp_id;
快速删除全表数据
-- Oracle、MySQL、Microsoft SQL Server以及PostgreSQL
TRUNCATE TABLE emp_devp;
DELETE 语句通过 WHERE 子句删除指定的数据行,如果不指定过滤条件将会删除所有的数据。DELETE 属于数据操作语言(DML),删除数据后可以选择提交或者回滚,如果删除的数据较多时速度比较慢。
TRUNCATE 语句用于快速删除表中的所有数据,并且释放表的存储空间。TRUNCATE 属于数据定义语言(DDL),删除数据时默认提交,无法回滚。TRUNCATE 语句相当于删除并重建表,通常执行速度很快。
合并数据
标准合并语句
-- Oracle、Microsoft SQL Server 以及 PostgreSQL
MEGRE INTO target_table [AS t_alias]
USING source_table [AS s_alias]
ON (conditions)
WHEN MATCHED THEN
UPDATE
SET col1 = expr1,
col2 = expr2,
...
WHEN NOT MATCHED THEN
INSERT (col1, col2, ...)
VALUES (expr1, expr2, ...);
-- Oracle、Microsoft SQL Server 以及 PostgreSQL
MERGE INTO emp_devp t
USING (SELECT emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email
FROM employee
WHERE dept_id = 4) s
ON (t.emp_id = s.emp_id)
WHEN MATCHED THEN
UPDATE
SET t.emp_name = s.emp_name, t.sex = s.sex,
t.dept_id = s.dept_id, t.manager = s.manager,
t.hire_date = s.hire_date, t.job_id = s.job_id,
t.salary = s.salary, t.bonus = s.bonus,
t.email = s.email
WHEN NOT MATCHED THEN
INSERT (emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email)
VALUES (s.emp_id, s.emp_name, s.sex, s.dept_id, s.manager,
s.hire_date, s.job_id, s.salary, s.bonus, s.email);
SELECT emp_id, emp_name
FROM emp_devp;
emp_id|emp_name
------|--------
9|赵云
10|廖化
11|关平
12|赵氏
13|关兴
14|张苞
15|赵统
16|周仓
17|马岱
DELETE
FROM emp_devp
WHERE emp_name = '赵云';
UPDATE emp_devp
SET salary = 5000,
email = 'liaohua@shuguo.net'
WHERE emp_name = '廖化';
-- Oracle、Microsoft SQL Server 以及 PostgreSQL
MERGE INTO emp_devp t
USING (SELECT emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email
FROM employee
WHERE dept_id = 4) s
ON (t.emp_id = s.emp_id)
WHEN NOT MATCHED THEN
INSERT (emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email)
VALUES (s.emp_id, s.emp_name, s.sex, s.dept_id, s.manager,
s.hire_date, s.job_id, s.salary, s.bonus, s.email);
-- Oracle
MERGE INTO emp_devp t
USING (SELECT emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email
FROM employee
WHERE dept_id = 4) s
ON (t.emp_id = s.emp_id)
WHEN MATCHED THEN
UPDATE
SET t.emp_name = s.emp_name, t.sex = s.sex,
t.dept_id = s.dept_id, t.manager = s.manager,
t.hire_date = s.hire_date, t.job_id = s.job_id,
t.salary = s.salary, t.bonus = s.bonus,
t.email = s.email
DELETE WHERE t.emp_name = '赵氏'
WHEN NOT MATCHED THEN
INSERT (emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email)
VALUES (s.emp_id, s.emp_name, s.sex, s.dept_id, s.manager,
s.hire_date, s.job_id, s.salary, s.bonus, s.email);
-- Microsoft SQL Server、PostgreSQL
MERGE INTO emp_devp t
USING (SELECT emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email
FROM employee
WHERE dept_id = 4) s
ON (t.emp_id = s.emp_id)
WHEN MATCHED AND t.emp_name = '赵氏' THEN
DELETE
WHEN MATCHED THEN
UPDATE
SET t.emp_name = s.emp_name, t.sex = s.sex,
t.dept_id = s.dept_id, t.manager = s.manager,
t.hire_date = s.hire_date, t.job_id = s.job_id,
t.salary = s.salary, t.bonus = s.bonus,
t.email = s.email
WHEN NOT MATCHED THEN
INSERT (emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email)
VALUES (s.emp_id, s.emp_name, s.sex, s.dept_id, s.manager,
s.hire_date, s.job_id, s.salary, s.bonus, s.email);
非标准合并语句
-- MySQL
INSERT INTO emp_devp(emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email)
SELECT emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email
FROM employee s
WHERE dept_id = 4
ON DUPLICATE KEY UPDATE
emp_name = s.emp_name, sex = s.sex,
dept_id = s.dept_id, manager = s.manager,
hire_date = s.hire_date, job_id = s.job_id,
salary = s.salary, bonus = s.bonus,
email = s.email;
-- PostgreSQL和SQLite
INSERT INTO emp_devp(emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email)
SELECT emp_id, emp_name, sex, dept_id, manager,
hire_date, job_id, salary, bonus, email
FROM employee s
WHERE dept_id = 4
ON CONFLICT(emp_id) DO UPDATE
SET emp_name = EXCLUDED.emp_name, sex = EXCLUDED.sex,
dept_id = EXCLUDED.dept_id, manager = EXCLUDED.manager,
hire_date = EXCLUDED.hire_date, job_id = EXCLUDED.job_id,
salary = EXCLUDED.salary, bonus = EXCLUDED.bonus,
email = EXCLUDED.email;
外键约束与级联操作
违反外键约束
-- 违反外键约束,职位不存在
INSERT INTO employee (emp_name, sex, dept_id, manager, hire_date,
job_id, salary, bonus, email, comments,
create_by, create_ts, update_by, update_ts)
VALUES ('马超', '男', 5, 18, CURRENT_DATE, -- Microsoft SQL Server 需要替换该函数
11, 6000, NULL, 'machao@shuguo.com', NULL,
'Admin', CURRENT_TIMESTAMP, NULL, NULL);
-- 违反外键约束,职位不存在
UPDATE employee
SET job_id = 11
WHERE emp_id = 1;
-- 违反外键约束,存在子记录
DELETE
FROM job
WHERE job_id = 1;
级联更新和删除
CREATE TABLE t_parent(id INTEGER PRIMARY KEY);
INSERT INTO t_parent(id) VALUES (1);
CREATE TABLE t_child(
id INTEGER PRIMARY KEY,
pid INTEGER NOT NULL,
CONSTRAINT fk1 FOREIGN KEY (pid) REFERENCES t_parent(id)
ON UPDATE CASCADE -- Oracle不支持该选项
ON DELETE CASCADE
);
INSERT INTO t_child(id, pid) VALUES (1, 1);
INSERT INTO t_child(id, pid) VALUES (2, 1);
-- MySQL、Microsoft SQL Server、PostgreSQL以及SQLite
UPDATE t_parent
SET id = 3
WHERE id = 1;
SELECT * FROM t_child;
id|pid
--|---
1| 3
2| 3
DELETE
FROM t_parent
WHERE id = 3;
SELECT * FROM t_child;
id|pid
--|---
NO ACTION,如果父表上的UPDATE或者DELETE语句违反外键约束则返回错误,数据库在事务提交(COMMIT)时检查是否违反约束。
RESTRICT,如果父表上的UPDATE或者DELETE语句违反外键约束则返回错误,数据库在语句执行时立即检查是否违反约束。
CASCADE,如果在父表上执行UPDATE或者DELETE语句,级联更新或者删除子表上的记录。
SET NULL,如果在父表上执行UPDATE或者DELETE语句,将子表中的外键字段设置为NULL。
SET DEFAULT,如果在父表上执行UPDATE或者DELETE语句,将子表中的外键字段设置为默认值。