Oracle MERGE command and multi-table update and restore mechanism Flashback Data Sheet

First, the multi-table update

For example, there is a line of a module system due to the abnormal, leading to overall system data error has occurred, you need to manually rewrite the database error, Oracle update statement updates the values ​​from another table

update basic grammar format

UPDATE TABLE_NAME SET COLUMN1 = VALUE1 WHERE COLUMN2 = VALUE2

First, create the following two tables, so that the table is named 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', 'national network of Jinzhou New Area', '123445', TO_DATE ( '2019-11-29 10:25:23', 'YYYY-MM-DD HH24: MI: SS'), null);
INSERT INTO GF_CONS_TRAN_TEST VALUES ( '0002', 'Dalian power company', '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', 'Zhongshan power company', '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 table structure and data was as follows:

And then create a structure similar to Table A Table 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', 'national network of Jinzhou New Area _ updates', '123445', null);
INSERT INTO GF_CONS_TRAN_TEST_COPY VALUES ( '0003', '_ Update Zhongshan power company', '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");

Structure and Data Table B below

It can be seen that the first table (GF_CONS_TRAN_TEST AS A) has three data, the second table (GF_CONS_TRAN_TEST_COPY AS B) has two data fields have the same ID , (or else there is no update condition), assumed here to update a table USENAME listed in table B data, because there is a unique primary key ID indexing, we can write

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

The results show that the update is successful, but the affected line is the 3 -line, we look at the table after the A update data

Table B since no records 0002 , just as with the statement WHERE A.ID = B.ID so Table A data to update all table B are not shown as empty, so that not the whole data before , but the boss did not say that, ah,

Fortunately, Oracle database when we insert, update, delete, etc., prone to misuse, leading to other content database is modified by an ordinary sql statement can not be reverted, can be Oracle Flashback database table mechanism, according to the time stamp,

Second, the reduction table

1. Are the first query this point in time the data you want to restore data

SELECT
	*
FROM
	TABLENAME AS OF TIMESTAMP TO_TIMESTAMP (
		'2019-07-05 08:50:00',
		'YYYY-MM-DD HH24:MI:SS'
	) - Data Table certain time period

 

Raw data we can see the data for the previous update

2. open flashback mechanism this table

ALTER TABLE TABLE_NAME ENABLE ROW MOVEMENT

3. state flash back to the table this time

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

4. Close this table flashback state (Do not forget to perform this step)

ALTER TABLE TABLE_NAME DISABLE ROW MOVEMENT

Finished'll find table A data has been restored to its state prior to this time, because before you write the update statement updates all records, so we add a restriction, when the B table records the primary key ID in Table A start there in update, SQL statement is as follows:

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)

 

We can see this time update the two records, and we think exactly the same, back to Table A data

These two data we have just updated data and 0002 data has not changed, in line with the original requirements

Three, MERGE command

In oracle9g introduced MERGE command may be a sql on a table while statement insert and update operations, Merge command line to be selected from one or more data sources update or insert into one or more tables.

Merge into action is to solve the B table with the new A table data, if A table does not, put the B table data insertion A table or insert data into a table, if the table has the data is updated, if not then inserted.

Generally, we perform an insert statement like this

INSERT INTO GF_CONS_TRAN_TEST (ID, USERNAME, PASSWORD) VALUES ( '0004', 'national network Zhuanghe supply', 'zh_org')

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

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

B表数据不变

B表中有0001A表中没有,0003A表中存在,0002B表中没有,如果没有出错应该是更新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)

执行结构如下:

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

 

 

 

 

 

 

 

Guess you like

Origin www.cnblogs.com/LiuFqiang/p/11965943.html