一、多表更新

比如线上有个系统由于某一个模块出现异常,导致系统整体的数据出现了错误,需要你手动改写数据库错误,Oracle update语句更新的值来自另一张表

update语法最基本的格式为

UPDATE TABLE_NAME SET COLUMN1 = VALUE1 WHERE COLUMN2 = VALUE2

下面首先来创建两张表,令表名为GF_CONS_TRAN_TEST  AS A

-- ----------------------------
-- Table structure for GF_CONS_TRAN_TEST
-- ----------------------------
CREATE TABLE GF_CONS_TRAN_TEST (
"ID" VARCHAR2(64 BYTE) NOT NULL ,
"USERNAME" VARCHAR2(255 BYTE) NULL ,
"PASSWORD" VARCHAR2(255 BYTE) NULL ,
"CREATEDATE" DATE NULL ,
"PHONE" VARCHAR2(255 BYTE) NULL
)
LOGGING
NOCOMPRESS
NOCACHE ; -- ----------------------------
-- Records of GF_CONS_TRAN_TEST
-- ----------------------------
INSERT INTO GF_CONS_TRAN_TEST VALUES ('0001', '国网金州新区', '123445', TO_DATE('2019-11-29 10:25:23', 'YYYY-MM-DD HH24:MI:SS'), null);
INSERT INTO GF_CONS_TRAN_TEST VALUES ('0002', '大连供电公司', 'phhs_all', TO_DATE('2019-11-18 10:25:59', 'YYYY-MM-DD HH24:MI:SS'), null);
INSERT INTO GF_CONS_TRAN_TEST VALUES ('0003', '中山供电公司', 'zs_phs', TO_DATE('2019-11-29 10:26:49', 'YYYY-MM-DD HH24:MI:SS'), null); -- ----------------------------
-- Indexes structure for table GF_CONS_TRAN_TEST
-- ---------------------------- -- ----------------------------
-- Checks structure for table GF_CONS_TRAN_TEST
-- ----------------------------
ALTER TABLE GF_CONS_TRAN_TEST ADD CHECK ("ID" IS NOT NULL); -- ----------------------------
-- Primary Key structure for table GF_CONS_TRAN_TEST
-- ----------------------------
ALTER TABLE GF_CONS_TRAN_TEST ADD PRIMARY KEY ("ID");

A表结构及数据如下:

再创建一张和A表结构类似的表B ,GF_CONS_TRAN_TEST_COPY  AS B

-- ----------------------------
-- Table structure for GF_CONS_TRAN_TEST_COPY
-- ----------------------------
CREATE TABLE GF_CONS_TRAN_TEST_COPY (
"ID" VARCHAR2(64 BYTE) NOT NULL ,
"USERNAME" VARCHAR2(255 BYTE) NULL ,
"PASSWORD" VARCHAR2(255 BYTE) NULL ,
"CREATEDATE" DATE NULL
)
LOGGING
NOCOMPRESS
NOCACHE ; -- ----------------------------
-- Records of GF_CONS_TRAN_TEST_COPY
-- ----------------------------
INSERT INTO GF_CONS_TRAN_TEST_COPY VALUES ('0001', '国网金州新区_更新', '123445', null);
INSERT INTO GF_CONS_TRAN_TEST_COPY VALUES ('0003', '中山供电公司_更新', 'zs_phs', null); -- ----------------------------
-- Indexes structure for table GF_CONS_TRAN_TEST_COPY
-- ---------------------------- -- ----------------------------
-- Checks structure for table GF_CONS_TRAN_TEST_COPY
-- ----------------------------
ALTER TABLE "USER_PSSC"."GF_CONS_TRAN_TEST_COPY" ADD CHECK ("ID" IS NOT NULL); -- ----------------------------
-- Primary Key structure for table GF_CONS_TRAN_TEST_COPY
-- ----------------------------
ALTER TABLE GF_CONS_TRAN_TEST_COPY ADD PRIMARY KEY ("ID");

B表结构及数据如下

可以看到第一张表(GF_CONS_TRAN_TEST AS A)中有三条数据,第二张表(GF_CONS_TRAN_TEST_COPY AS B)有两条数据,都有相同的字段ID,(要不然没有更新条件),假设这里需要更新A表中的USENAME列为表B中的数据,因为有唯一主键ID做索引,我们可以这样写

UPDATE GF_CONS_TRAN_TEST A SET A.USERNAME = (
SELECT B.USERNAME FROM GF_CONS_TRAN_TEST_COPY B WHERE A.ID = B.ID
)

结果显示更新成功,但是受影响的行是3行,我们再看下表A更新后数据

由于表B中没有记录0002,因为用刚才的语句 WHERE A.ID = B.ID所以将表A的数据全部给更新了,表B中没有的显示为空了,所以说把之前的数据整没了,但是老板可没这么说啊,

幸好,Oracle数据库在我们执行插入、更新、删除等操作时,容易产生误操作,导致数据库其他的内容被修改,通过普通的sql语句操作无法还原,可采用Oracle数据库表的闪回机制,根据时间戳,

二、还原表

1.先查询这个时间点的数据是否为要还原的数据

SELECT
*
FROM
TABLENAME AS OF TIMESTAMP TO_TIMESTAMP (
'2019-07-05 08:50:00',
'YYYY-MM-DD HH24:MI:SS'
) --表某个时间段的数据

可以看到数据为我们更新之前的原始数据

2.开启这张表的闪回机制

ALTER TABLE TABLE_NAME ENABLE ROW MOVEMENT

3.把表的状态闪回到这个时间段

FLASHBACK TABLE TABLE_NAME  TO TIMESTAMP TO_TIMESTAMP('2019-11-29 11:00:00','YYYY-MM-DD HH24:MI:SS')

4.关闭这张表的闪回状态(切勿忘记执行该步骤)

ALTER TABLE TABLE_NAME DISABLE ROW MOVEMENT

执行完毕会发现表A的数据已经还原到这个时间之前的状态了,因为之前写的update语句会更新全部的记录,所以我们加入限制条件,当B表的记录主键ID在表A中存在时开始更新,SQL语句如下:

UPDATE GF_CONS_TRAN_TEST A SET A.USERNAME = (SELECT B.USERNAME FROM GF_CONS_TRAN_TEST_COPY B WHERE A.ID = B.ID)
WHERE EXISTS (SELECT 1 FROM GF_CONS_TRAN_TEST_COPY B WHERE B.ID = A.ID)

我们可以看到这回更新了两条记录,与我们所想完全一致,回头查看表A的数据

这两条数据为我们刚才所更新的数据,并且0002数据没有变化,符合当初的要求

三、MERGE命令

在oracle9g引入了MERGE命令,可以在一个sql语句中对一个表同时进行insert和update操作,merge命令可以从一个或多个数据源中选择行来update或者insert到一个表或多个表。

Merge into的作用就是解决B表跟新A表数据,如果A表没有,则把B表数据插入A表或向一个表中插入数据,如果该表有该数据则更新,如果没有则插入。

一般我们执行插入语句会是这样

INSERT INTO GF_CONS_TRAN_TEST (ID, USERNAME, PASSWORD) VALUES('0004','国网庄河供电','zh_org')

当然对于主键ID来说常用的两种方式就是UUID和自增长了,很少会出现主键重复的问题,但是假如在插入数据的时候根据主键4判断,如果没有插入数据,如果有则根据ID来更新,岂不一举两得

为了可以看到效果,我们手动更新A表数据如下

B表数据不变

B表中有0001在A表中没有,0003在A表中存在,0002在B表中没有,如果没有出错应该是更新0003,插入0001,SQL执行如下:

MERGE INTO GF_CONS_TRAN_TEST A USING (SELECT B.ID, B.USERNAME, B.PASSWORD FROM GF_CONS_TRAN_TEST_COPY B ) C ON (A.ID = C.ID)
WHEN MATCHED THEN
UPDATE SET A.USERNAME = C.USERNAME, A.PASSWORD = C.PASSWORD
WHEN NOT MATCHED THEN
INSERT (A.ID, A.USERNAME, A.PASSWORD) VALUES(C.ID, C.USERNAME, C.PASSWORD)

执行结构如下:

与我们所想一致,一条为更新操作,一条为新增操作。

Oracle多表更新及MERGE命令和闪回机制还原数据表的更多相关文章

  1. Oracle 中利用闪回查询确定某表在某时间点之后的修改内容,并恢复至该时间点

    Oracle 中利用闪回查询确定某表在某时间点之后的修改内容: 1.查看 DELETE 及 UPDATE 操作修改的数据: SQL> SELECT * FROM tab AS OF TIMEST ...

  2. Oracle Flashback Technologies - 闪回被drop的表

    Oracle Flashback Technologies - 闪回被drop的表 在oracle10g中,drop一个表后,表没有真正被删除,支持被rename后放在recyclebin中. #新建 ...

  3. Oracle闪回恢复误删除的表、存储过程、包、函数...

    在日常的数据库开发过程汇总难免会出现一些误删除的动作, 对于一些误删的操作我们可以通过oracle提供的闪回机制恢复误删数据, 从而避免出现较大的生产事故. 下面是本人平时工作中积累的一些常用的操作, ...

  4. 【oracle11g,13】表空间管理2:undo表空间管理(调优) ,闪回原理

    一.undo空间原理: dml操作会产生undo数据. update时,sever process 会在databuffer 中找到该记录的buffer块,没有就从datafile中找并读入data ...

  5. SQL Fundamentals: 表的创建和管理(表的基本操作,闪回技术flashback,表结构修改)

    SQL Fundamentals || Oracle SQL语言 1.表的基本操作 (CREATE TABLE, DROP TABLE,TRUNCATE TABLE, RENAME tablename ...

  6. ORACLE闪回机制分析与研究应用

    1.查看数据库归档和闪回状态,及环境准备SQL> archive log list;SQL> select flashback_on from v$database;关闭数据库,启动归档和 ...

  7. Oracle的闪回技术--闪回已删除的表

    注意闪回技术只能保护非系统表决空间中的表,而且表空间必须本地管理, 外键将不可以被恢复, 索引和约束的名字将会被命名为以BIN开头,由系统生成的名字 查看是否开启闪回: SQL> show pa ...

  8. 【Oracle】闪回drop后的表

    本文介绍的闪回方式只适用于:删除表的表空间非system,drop语句中没有purge关键字(以上两种情况的误删除操作只能通过日志找回): 1.删除表后直接从回收站闪回 SCOTT@LGR> d ...

  9. 己亥清爽恢复系列之数据文件4篇:DROP表后如何恢复(非闪回技术)

    己亥清爽系列说明:清爽系列是作为恢复系列的基础篇,基于FS(File System)文件系统的手工还原恢复,也叫基于用户管理的还原恢复,来自于博客园AskScuti. 实验说明:你不小心Drop掉了一 ...

随机推荐

  1. sql 摘抄

    练习题和参考解 (1)查询“001”课程比“002”课程成绩低的所有学生的学号.001学科成绩.002学科成绩                 1 SELECT 2 s1.StudentNo, 3 s ...

  2. UVA1411 Ants

    想出的一道题竟然是原题QAQ 非常有趣的一个题 根据三角形两边之和大于第三边 所以相交的线段一定是比不相交的线段要长的 所以直接二分图构图 最小费用最大流即可 (我不管我不管我要把这个出到NOIP膜你 ...

  3. Delphi 版本信息获取函数 GetFileVersionInfo、GetFileVersionInfoSize、VerFindFile、VerInstallFile和VerQueryValue

    一.版本信息获取函数简介和作用 获取文件版本信息的作用: 1. 避免在新版本的组件上安装旧版本的相同组件: 2. 在多语言系统环境中,操作系统根据文件版本信息里提供的语言信息在启动程序时决定使用的正确 ...

  4. MariaDB 删除表

    在本章中,我们将学习删除表. 表删除很容易,但记住所有删除的表是不可恢复的. 表删除的一般语法如下 - DROP TABLE table_name ; 存在执行表删除的两个选项:使用命令提示符或PHP ...

  5. 【多线程】ConcurrentLinkedQueue 的实现原理

    1. 引言 在并发编程中我们有时候需要使用线程安全的队列.如果我们要实现一个线程安全的队列有两种实现方式:一种是使用阻塞算法,另一种是使用非阻塞算法.使用阻塞算法的队列可以用一个锁(入队和出队用同一把 ...

  6. STM32点LED灯

    一.建立项目模板 这里的user中重复引用了system_stm32f10x.c Output中选择Create HEXFile,并且可以选择输出路径. Listing中可以选择输出路径. 然后在C/ ...

  7. 大碗宽面Beta阶段第十一周会议记录

    本周二晚上我们在宿舍楼的大厅进行了本周的小组会议,虽然天气很冷,但大家都还是如数到场,积极参加小组会议.对于上周的任务大家都努力完成,在前端方面,大家完善了主页面和一些分页面,主要有导航栏界面的完成. ...

  8. js控制ios端的input/textarea元素失去焦点时隐藏键盘

    同事在测试产品时发现这样一个:“某些页面击完input框,在点空白处时,iOS设备的键盘不能隐藏并且焦点也不会失去” 带着这个问题我进行了测试,发现在安卓的设备上并没有这种问题出现. 于是写js进行测 ...

  9. mysql5.7-my.cnf

    [client] port = socket=/tmp/my3306.sock [mysql] no-auto-rehash [mysqld] #########base############ us ...

  10. 一次且仅一次(once and only once,简称OAOO)

    一次且仅一次(once and only once,简称OAOO)又称为 Don't repeat yourself(不要重复你自己,简称DRY)或一个规则,实现一次(one rule, one pl ...