数据库概论.陈立军.04. 数据更新
数据更新
- Insert
- Delete
- Truncate
- Update
- Output
- Merge
全局变量
row_count()
- 返回受上一语句影响的行数
- 任何不返回行的语句将这一变量设置为 0
- 例子:删除了多少行
1 | delete from S |
Insert
- 形式
1 | /* 插入一条指定好值的行 */ |
插入显式行
1 | insert into PROF values |
插入子查询
- 将平均成绩大于 90 的学生加入到 EXCELLENT 中
1 | insert into EXCELLENT (sno, grade) |
replace into
- 替换原有的数据行
1 | create table test_replace( |
Delete
- 从表中删除符合条件的元组
- 如果没有 where 语句,则删除所有元组
1 | delete from 表名 [where 条件表达式] |
1 | /* 清除所有选课记录 */ |
- 删除的时候,用 in 而不是 =
- 可能有两个人都叫王明,使用 = 会报错
- 运行时错误
1 | create table delA(a int); |
- 可以使用
limit 1
限制只输出一行
1 | delete from delB |
多表删除操作
1 | delete t1,t2 from t1 inner join t2 inner join t3 |
1 | delete PC from PROF inner join PC |
删除操作
例子
- 删除低于平均工资的老师记录
1 | /* 这样的语句是错误的 */ |
- 思考:是先找到所有符合条件的行,一并删除,还是找到一个删除一个
- 应该是先找到,然后会一并删除
- 删除的时候会加锁,一并删除可以保持对外的一致性
- MySQL 不允许从子查询中出现的表中删除数据
- 解决方法,先找出平均工资,然后再删除
1 | /* 生成临时视图 */ |
Truncate
- 清空表
1 | truncate table |
- 删除表中的所有行,而不记录单个行删除操作
- 相对于用 delete 语句删除整个表而言,更加高效
- 数据库一般都有日志记录,用于恢复数据库
- delete 删除一个表会产生行级的记录
- truncate 删除整个表只会产生页级的记录
- truncate table 在功能上与不带 where 子句的 delete 语句相同
- 但 truncate table 比 delete 速度快,且使用的系统和事务日志资源少
- auto_increment 计数器重置为种子值
Update
- 更新操作的命令格式
1 | update 表名 |
- 指定对哪些列进行更新,以及更新后的值是什么
例子 1
- 老师工资上调 5%
1 | update PROF |
- 将 D01系系主任的工资改为该系的平均工资
1 | /* SQL 语句无效 */ |
- 解决方法是一致的,临时视图
1 | with tmp as(select avg(salary) avgsal from PROF where dno=D01) |
例子 2
- 当 C1 课程的成绩小于该课程的平均成绩时,将其提高 5%
1 | with tmp as(select avg(grade) avggrade from SC where cno=C1) |
- 对所有的课程,满足上述条件的都进行修改
1 | with tmp as( |
例子 3 (case when)
- 工资超过 2000 的缴纳 10% 所得税,其余的缴纳 5% 所得税
- 如果写成两个 SQL,需要考虑执行顺序
- 这里需要先写 5% 的征税(工资小于等于2000),再写 10% 的征税(工资大于2000)
- 写成多个 SQL 是不好的习惯
- 最好写成一个 SQL
case when
1 | update PROF |
Merge
行拷贝
- R(ID, A, B), S(ID, A, B)
- 使用 S 相同 ID 的记录覆盖 R 中相同 ID 的记录
1 | /* 错误的写法 */ |
- 怎么处理呢?
- 表同步问题
表同步: UPSERT
- UPSERT:表同步
- 在把一组记录加载到表中时,一个经典的挑战是如何识别和处理目标表中已有的记录
- 常用的方法如下
- 如果某记录不存在,就将它插入
- 如果存在,就用源表中的数据更新该记录
- 需要定义复杂的存储过程来完成一系列 INSERT 或 UPDATE 命令,这个技术通常被称为 UPSERT
- 应用场景
- 业务表不能够一直增大,否则会拖慢系统的性能,因此需要定时保存到历史表中
Merge 命令
- merge 子句指定作为插入、更新或删除操作目标的表
- using 子句指定要与目标联接的数据源
- on 子句指定决定目标与源的匹配位置的联接条件
- when 子句基于 on 子句的结果指定所要采取的操作
- when matched
- when not matched by target
- when not matched by source
表同步一个典型的应用场景
- 数据仓库中的 FactBuyingHabits 表跟踪客户购买产品的最后日期,事务数据库每周都会生成一个包括该周采购情况的PurchaseRecords 表
- 需要定期将 PurchaseRecords 表中的信息合并到 FactBuyingHabits 表中
- 对于不存在的产品-客户对,插入新行
- 对于已存在的产品-客户对,更新最近的购买日期
1 | /* 指定目标表 */ |
- Merge 命令的产生是源于本是据数据仓库的发展
- 更新操作对于数据库而言是很关键的,一般会有记录(谁更新了什么)
- 审计
Output
- Output:记录更新历史
- 执行修改操作只返回影响了多少行的信息,无从获知到底影响到了哪些行
- 如果在修改操作语句中带上output,就可以输出具体的影响信息
1 | output{ deleted|inserted}.{ * | column_name} |
- deleted 和 inserted 是两个虚表,deleted 里面存放修改之前的值,inserted 里面存放的是修改之后的值
1 | declare @recordChange table( |