使用Oracle 10gMERGE语句更新数据行

在Oracle 9i R2版中引入的MERGE语句通常被称作“更新插入”(upsert),因为使用MERGE可以在同一个步骤中更新(update)并插入(insert)数据行,对于抽取、转换和载入类型的应用软件可以节省大量宝贵的时间,比如向数据仓库中加载数据,数据仓库中没有的数据行可以插入到数据仓库中,而已经存在的数据行也同时被更新。

在MERGE语句引入的时候,需要同时使用一条UPDATE和一条INSERT语句,顺序也是固定的(先使用UPDATE语句,然后是INSERT语句)。如果您只需要使用其中的某一条一句,您只需要使用现有的INSERT或者UPDATE语句,而不必使用MERGE语句,而删除数据可以使用DELETE语句。

在Oracle 10g R1版中,MERGE语句发生了变化,UPDATE或INSERT语句不再是必须的,而是可选项,您可以两者都用也可以都不用,而且,UPDATE语句也具备了DELETE的功能,您可以在同一个步骤中对现有的有效记录进行升级并清理废弃的记录。

列表A创建了一个表格列出现有项目:项目号码、标题、开始日期、进度完成比例以及员工对项目的响应,还创建了一个事务表格使用MERGE语句进行升级批处理。

DROP TABLE open_projects;
   DROP TABLE project_updates;
   CREATE TABLE open_projects
   (pno NUMBER(6) PRIMARY KEY,
   title VARCHAR2(40),
   startdate DATE,
   pctdone NUMBER(3),
   empno NUMBER(6)
   );
   INSERT INTO open_projects VALUES
   (10, 'Inventory servers', '08-JAN-07',0, 206);
   INSERT INTO open_projects VALUES
   (20, 'Upgrade Oracle on SRV01','15-JAN-07', 0, 206);
   INSERT INTO open_projects VALUES
   (30, 'Conduct skills assessment','22-JAN-07', 0, 210);
   CREATE TABLE project_updates
   (action CHAR(1),
   pno NUMBER(6),
   pctdone NUMBER(3),
   empno NUMBER(6)
   );
   INSERT INTO project_updates VALUES
   ('C', 10, 50, 214);
   INSERT INTO project_updates VALUES
   ('D', 20, NULL, NULL);
   COMMIT;

列表A

 一个典型的MERGE语句从识别表格开始执行升级,而且对现有的记录进行筛选测试:

MERGE INTO open_projects op
   USING project_updatespu
   ON (op.pno = pu.pno)
   ...

表格open_projects会接受更新的数据,而project_updates表格则不会改变,如果项目号码(pno)在两个表格中都一样,那么数据行则被认为是相同的。

MERGE语句剩下的部分是更新语句,以及DELETE WHERE语法。

...
   WHEN MATCHED THEN
   UPDATE SET pctdone = pu.pctdone,
   empno = pu.empno
   DELETE
   WHERE pu.action = 'D';

列表B展示了MERGE语句运行前后的表格情况。

SQL> @mergedel_b
   PNO TITLE STARTDATE PCTDONE EMPNO
   ---------- ---------------------------------------- --------- ---------- ----------
   10 Inventory servers 08-JAN-07 0 206
   20 Upgrade Oracle on SRV01 15-JAN-07 0 206
   30 Conduct skills assessment 22-JAN-07 0 210
   A PNO PCTDONE EMPNO
   - ---------- ---------- ----------
   C 10 50 214
   D 20
   2 rows merged.
   PNO TITLE STARTDATE PCTDONE EMPNO
   ---------- ---------------------------------------- --------- ---------- ----------
   10 Inventory servers 08-JAN-07 50 214
   30 Conduct skills assessment 22-JAN-07 0 210
   A PNO PCTDONE EMPNO
   - ---------- ---------- ----------
   C 10 50 214
   D 20
   SQL> spool off

列表B

第一个事务对第10号项目进行了改变(操作‘c’),项目完成比例从0变成了50,项目员工人数变成了214人;第二个事务产出了第20号项目,“随后”的列表展示了删除后的状态,而project_updates表格没有发生改变。这个例子展示了这些语句并不是必须的,而且在MERGE语句中也并不需要使用INSERT语句。

时间: 2024-11-09 13:36:26

使用Oracle 10gMERGE语句更新数据行的相关文章

oracle sql语句统计数据写法

问题描述 oracle sql语句统计数据写法 有3张表,A表活动B表活动地区C表地区商家 A表关联B表,B表关联C表都是一对多,现在需返回活动名称,活动地区数,地区商家数 解决方案 SELECT A.活动名称COUNT(1)SUM(SELECT COUNT(1) FROM C WHERE A=B AND B=C) FROM A INNER JOIN B ON A=B GROUP BY A.活动名称 解决方案二: SELECT T1.活动 AS 活动名称 COUNT(T2.地区) AS 活动地区

求oracle sql语句统计数据

问题描述 求oracle sql语句统计数据 求oracle sql语句统计数据 要统计出勤率.迟到次数.旷工次数 签到表(ManualSign) 字段: SignId:签到表的ID ,UserId:用户ID ,SignTime:签到时间 ,SignDesc:签到备注 ,SignTag:签到标记(签到.签退) 样例记录:13, 'jiyaoqi', to_date('2015-08-18 08:00:00' ,'yyyy-MM-dd hh24:mi:ss'), '测试一下', 1 工作时间表(W

Oracle中DBMS_ROWID定位数据行物理存储位置

对于oracle中的堆表,我们可以通过oracle内置的ROWID伪列得到对应行记录所在的ROWID的值(注意,这个ROWID只是一个伪列,实际的块中并不存在该列).然后我们可以通过DBMS_ROWID包中的相关方法来通过ROWID伪列来定位对应数据行的实际物理存储物理地址. dbms_rowid.rowid_relative_fno:定位该数据行所在的数据文件 dbms_rowid.rowid_block_number:定位该数据行在数据文件的第多少个块 dbms_rowid.rowid_ro

myDataAdapter 更新数据问题

问题描述 我使用如下的语句更新数据表时,数值.时间.逻辑类型的可以更新,但是字符类型的不能更新,不知道为什么?希望高手指点,其中System.Data.OleDb.OleDbCommandBuildermyCommandBuilder;myDataAdapter=newOleDbDataAdapter(ShowSql,conn);datagridview1.EndEdit();//生成Delete/Update/Insert操作的CommandmyCommandBuilder=newSystem

DataAdapter 更新数据问题

问题描述 我使用如下的语句更新数据表时,数值.时间.逻辑类型的可以更新,但是字符类型的不能更新,不知道为什么?希望高手指点,真是郁闷.System.Data.OleDb.OleDbCommandBuildermyCommandBuilder;myDataAdapter=newOleDbDataAdapter(ShowSql,conn);datagridview1.EndEdit();//生成Delete/Update/Insert操作的CommandmyCommandBuilder=newSys

更新多行数据,然后把更新的结果读出来,这样的 SQL 要怎么写?

考虑这样一种场景,或许还挺常见的:我们需要在关系数据库中更新一行或多行数据的多个字段,更新完了还不算,还得拿到被更新的某一个字段的结果. 再考虑这样一种场景:我们需要在关系数据库中更新一行或多行数据的多个字段,更新完了还不算,还得拿到这批被更新的记录的主键,以便操作其他的有关联的表. 这么说也许太抽象,就拿点赞计数来打个比方(做为点赞狂魔的我,前不久才在朋友的 博文 下面强行点了 666 个赞). 假设有这样一张表,就叫 likes 好了,记录了一个网站里面每个能被点赞的对象被赞的次数.id 是

oracle千万数据快速查找满足max条件的数据行示例

场景 假设我们有这样的一个访问记录表accessTable,记录项分别为用户唯一标识(userId).访问时间(visitTime).访问时上报的版本信息(ver).需求为查询每个用户最近一次访问时上报的版本是什么,环境是在oracle下.本人非DBA,有问题一定要指出来啊. 思路一 使用oracle的分析函数.具体函数使用见这里. SELECT * FROM (SELECT t.userId, t.visitTime, t.ver, Row_number() OVER( partition B

C#中SQLserver语句insert语句无法更新数据

问题描述 C#中SQLserver语句insert语句无法更新数据 string sqlUpdataString = "insert into RelationTab(RelationId,FoodId,OrderId,FoodName,FoodPrice) values(" + RelationIdMax + "," + FoodId + "," + OrderId + ",'" + FoodName + "',&

ORACLE学习笔记-添加更新数据函数篇_oracle

一.添加数据 /*添加数据*/ insert into STU values('stu0004','赵一',18,1,"kc0004"); insert into STU(STU_ID,STU_NAME,STU_AGE,STU_SET ) values('stu0013','储十一',19,1); 说明:如果不指定将数据添加到那个字段,那么此时必须列出全部数据,如果列出字段,则一一对应,必须列出约束不为空的所有字段,否则报错. 二.更新数据 /*更新数据*/ update STU SE