`
changhongbao
  • 浏览: 116291 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Oracle笔记(七) 数据更新、事务处理、数据伪列

 
阅读更多

一、数据的更新操作

DML操作语法之中,除了查询之外还有数据的库的更新操作,数据的更新操作主要指的是:增加、修改、删除数据,但是考虑到emp表以后还要继续使用,所以下面先将emp表复制一份,输入如下指令:

CREATE TABLE myemp AS SELECT * FROM emp;

这种语法是Oracle中支持的操作,其他数据库不一样。

1、数据增加

如果现在要想实现数据的增加操作,则可以使用如下的语法完成:

INSERT INTO 表名称 [(字段1,字段2,…)] VALUES(值1,值2,…);

如果要想进行增加数据的话,则以下的几种数据类型要分别处理:

  • 增加数字:直接编写数字,例如:123;
  • 增加字符串:字符串应该使用“’“声明;
  • 增加DATE数据:
    • 第一种:可以按照已有的字符串的格式编写字符串,例如“’17-12月-80’”;
    • 第二种:利用TO_DATE()函数将字符串变为DATE型数据;
    • 第三种:如果设置的时间为当前系统时间,则使用SYSDATE;

可是对于数据的增加也有两种操作格式:完整型、简便型;

范例:增加数据 —— 完整语法编写

INSERT INTO myemp(empno,ename,hiredate,sal,mgr,job,comm)
VALUES(8888,'张三',TO_DATE('1960-08-17','yyyy-mm-dd'),8000,7369,'清洁工',1000);
INSERT INTO myemp(empno,ename,hiredate,sal,mgr,job,deptno)
VALUES(8889,'李四',SYSDATE,3000,7369,'清洁工',30);

范例:增加数据 —— 简便语法,不写增加的列名称

INSERT INTO myemp VALUES(8889,'李四','清洁工',7369,SYSDATE,3000,null,30);

很明显虽然简便语法代码少了,可是这种操作并不可取,所以在实际的开发之中,没有任何一个人会写简便语法,这样根本就不利于程序的维护,都编写完整的操作。

2、数据修改

如果要想修改表中已有的数据,则可以按照如下的语法进行:

UPDATE 表名称 SET 更新字段1=更新值1,更新字段2=更新值2,… [WHERE 更新条件(s)];

范例:更新雇员编号是7369的基本工资为5000,奖金为2000,职位修改为MANAGER,雇佣日期修改为今天

UPDATE myemp SET sal=5000,comm=2000,job='MANAGER',hiredate=SYSDATE WHERE empno=7369;

范例:所有人的工资改为7500

UPDATE myemp SET sal=7500;

如果更新时候不加上更新操作,则意味着更新全部的数据,但是这种做法绝对不可取,如果现在表中的数据量较大的话,这种更新所耗费的时间是相当长的,而且性能也会明显降低。

3、数据删除

当数据不再需要之后,就可以使用以下的语法删除数据:

DELETE FROM 表名称 [WHERE 删除条件(s)];

与更新一样,如果没有写删除条件的话,则表示删除全部数据;

范例:删除所有在1987年雇佣的雇员

DELETE FROM myemp WHERE TO_CHAR(hiredate,'yyyy')=1987;

一定要记住,如果删除的时候没有匹配条件的数据存在,则更新的记录为“0”,包括更新操作也是一样的。

范例:删除表中的全部记录

DELETE FROM myemp;

一般对于删除的操作而言,尽可能少去使用,包括以后在进行系统开发的时候,对于所有的删除操作之前实际上都建议大家先给出一个确认的提示框,以防止用户误删除。

二、事务处理

对于数据表的操作,很明显查询要比更新操作更加的安全,因为更新操作有可能会出现错误,以导致没有按照既定的要求正确的完成更新操作。

但是在很多时候更新有可能会有多条指令共同完成,例如:以银行转帐的方式为例:

  1. 判断A的账户上是否有5000W;
  2. 判断B账户是否存在并且状态是否正常;
  3. 从A的账户上移走5000W;
  4. 向B的账户之中增加5000W;
  5. 向银行支付手续费用5000;

以上的五个操作是一个整体,可以理解为一个完整的业务,如果这之中第三点出错了,那么其他的操作呢?所有的操作都应该不再执行,并且回归到最原始的状态,而这个操作流程就是事务的操作。

所有的事务处理操作都是针对于每一个session进行的,在Oracle数据库之中,把每一个连接到数据库上的用户都称为一个session,每一个session之间彼此独立,不会有任何的通讯,而每一个session独享自己的事务控制,而事务控制之中主要使用两个命令:

  • 事务的回滚:ROLLBACK,更新操作回到原点;
  • 事务的提交:COMMIT,真正的发出更新的操作,一旦提交之后无法回滚;

但是这样一来也会出现一些问题,例如:某一个session在更新数据表的时候还没有提交事务,其他session是无法更新的,必须等待之前的session提交后才可以;

这种问题从大的方面讲可以称为死锁,但是在Oracle之中死锁有很多的种类,这些与开发者没有太大的关系,是由DBA负责的。

所有的数据更新一定都会受到事务的控制。

三、数据伪列

数据伪列指的是用户不需要处理的列,而是由Oracle自行维护的数据列,在Oracle之中有两个数据伪列:ROWNUM、ROWID;

1、 ROWNUM

ROWNUM从单词含义上讲应该表示的是行号,实际上ROWNUM为每一个显示的记录都会自动的随着查询生成行号,例如,下面通过两个代码观察:

SELECT ROWNUM,empno,ename,job,hiredate,sal FROM emp;

此时的ROWNUM行号并不是永久固定的;

SELECT ROWNUM,empno,ename,job,hiredate,sal FROM emp WHERE deptno=30;

是每次动态的重新生成的,那么既然有了ROWNUM之后,下面就可以实现数据的部分显示;

范例:查询前5条记录

SELECT ROWNUM,empno,ename,job,hiredate,sal FROM emp
WHERE ROWNUM<=5;

范例:查询6-10条记录

按照正常的思维肯定是直接进行BETWEEN…AND的判断;

SELECT ROWNUM,empno,ename,job,hiredate,sal FROM emp
WHERE ROWNUM BETWEEN 6 AND 10;

这个时候并没有返回任何的数据,因为ROWNUM不是真实列,而要想真正的实现这种查询,思路是:先查询前10条记录,之后再显示后5条记录,要依靠子查询完成。

SELECT * FROM(
      SELECT ROWNUM m,empno,ename,job,hiredate,sal FROM emp
      WHERE ROWNUM<=10) temp
WHERE temp.m>5;

如果现在按照这个思路,下面就可以给出日后程序中所需要分页的功能实现。

范例:显示前5条记录

当前所在页(currentPage)为1;

每页显示的记录长度(lineSize)为5;

第一页:

SELECT * FROM(
      SELECT ROWNUM m,empno,ename,job,hiredate,sal FROM emp
      WHERE ROWNUM<=5) temp
WHERE temp.m>0;

范例:显示中间的5条记录

当前所在页(currentPage)为2;

每页显示的记录长度(lineSize)为5;

第二页:

SELECT * FROM(
      SELECT ROWNUM m,empno,ename,job,hiredate,sal FROM emp
      WHERE ROWNUM<=10) temp
WHERE temp.m>5;

范例:显示第三页的内容,currentPage=3,lineSize=10;

SELECT * FROM(
      SELECT ROWNUM m,empno,ename,job,hiredate,sal FROM emp
      WHERE ROWNUM<=15) temp
WHERE temp.m>10;

以上的程序就是分页显示操作的核心代码。

2、 ROWID

ROWID表示的是每一行数据保存的物理地址的编号,例如,观察如下的查询:

SELECT ROWID,deptno,dname,loc FROM dept;

此时返回许多的记录:

ROWID                  DEPTNO DNAME          LOC
------------------ ---------- -------------- -------------
AAAL+XAAEAAAAANAAA         10 ACCOUNTING     NEW YORK
AAAL+XAAEAAAAANAAB         20 RESEARCH       DALLAS
AAAL+XAAEAAAAANAAC         30 SALES          CHICAGO
AAAL+XAAEAAAAANAAD         40 OPERATIONS     BOSTON

每一条记录的ROWID都不会重复,所以即便表中所有列的数据内容都重复了,ROWID也是不会重复的,而且以一个ROWID为例,说明ROWID组成,例如:AAAL+XAAEAAAAANAAA

  • 数据对象号:AAAL+X;
  • 相对文件号:AAE;
  • 数据块号:AAAAAN;
  • 数据行号:AAA;

面试题:请删除表中的重复记录

现在项目之中由于管理不善,所以导致出现了许多重复的信息,为了说明问题,下面为表中增加若干条记录。

复制代码
INSERT INTO dept(deptno,dname,loc) VALUES (21,'RESEARCH','DALLAS');
INSERT INTO dept(deptno,dname,loc) VALUES (31,'SALES','CHICAGO');
INSERT INTO dept(deptno,dname,loc) VALUES (32,'SALES','CHICAGO');
INSERT INTO dept(deptno,dname,loc) VALUES (41,'OPERATIONS','BOSTON');
INSERT INTO dept(deptno,dname,loc) VALUES (42,'OPERATIONS','BOSTON');
INSERT INTO dept(deptno,dname,loc) VALUES (43,'OPERATIONS','BOSTON');
COMMIT;
复制代码

此时的数据显示是:

复制代码
SQL> select * from dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
        21 RESEARCH       DALLAS
        31 SALES          CHICAGO
        32 SALES          CHICAGO
        41 OPERATIONS     BOSTON
        42 OPERATIONS     BOSTON
        43 OPERATIONS     BOSTON

已选择10行。
复制代码

现在要求删除掉所有重复的记录,保留最早增加的记录内容。

最终显示效果:

复制代码
SQL> select * from dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
复制代码

先按照查询的方式做,首先找到所有重复的数据,重复的数据就比较容易了,按照部门名称及位置分组,之后统计个数,如果个数大于1,则表示重复。

SELECT dname,loc,MIN(ROWID)
FROM dept
GROUP BY dname,loc
HAVING COUNT(deptno)>1;

此时返回的三个ROWID,与最早的ROWID比较一下。

ROWID                  DEPTNO DNAME          LOC
------------------ ---------- -------------- -------------
AAAL+XAAEAAAAANAAA         10 ACCOUNTING     NEW YORK
AAAL+XAAEAAAAANAAB         20 RESEARCH       DALLAS
AAAL+XAAEAAAAANAAC         30 SALES          CHICAGO
AAAL+XAAEAAAAANAAD         40 OPERATIONS     BOSTON
复制代码
SQL> SELECT dname,loc,MIN(ROWID)
  2  FROM dept
  3  GROUP BY dname,loc
  4  HAVING COUNT(deptno)>1;

DNAME          LOC           MIN(ROWID)
-------------- ------------- ------------------
SALES          CHICAGO       AAAL+XAAEAAAAANAAC
RESEARCH       DALLAS        AAAL+XAAEAAAAANAAB
OPERATIONS     BOSTON        AAAL+XAAEAAAAANAAD
复制代码

数据插入的早,ROWID就小,所以下一步首先必须确定的是不能删除的ROWID,去掉之前的限制(COUNT()>1),表示按照部门名称及位置分组,取出每一个最小的ROWID;

SELECT MIN(ROWID)
FROM dept
GROUP BY dname,loc;

以上的数据是删除的,所以下面编写DELETE语句:

复制代码
DELETE FROM dept
WHERE ROWID NOT IN(
      SELECT MIN(ROWID)
      FROM dept
      GROUP BY dname,loc);
COMMIT;
复制代码

此时就是根据ROWID完成的,而这道题目也就是ROWID现在为止的唯一可以看的见的作用。

在所有的伪列之中,只有ROWNUM是以后开发之中最为重要的部分,一定要掌握,而对于ROWID知道就行了,不必做太深入的了解。

 
posted @ 2012-09-08 22:28 David_Tang 阅读(3919) 评论(8) 编辑 收藏

 
 
  
#1楼 2012-09-09 10:36 随风浪迹天涯  
LZ 
这个时候并没有返回任何的数据,因为ROWNUM不是真实列,而要想真正的实现这种查询,思路是:先查询前10条记录,之后再显示后5条记录,要依靠子查询完成。

这样子是可以滴。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SQL> select rownum,sname,ssex,sage,sdept from student where rownum between 1 a
 3;
 
    ROWNUM SNAME                SSEX             SAGE SDEPT
---------- -------------------- ---------- ---------- --------------------
         1 XiaoHong             Male               18 CS
         2 XiaoHua              Female             22 CS
         3 XiaoLan              Female             20 MA
 
SQL> select rownum,sname,ssex,sage,sdept from student where rownum between 1 a
 5;
 
    ROWNUM SNAME                SSEX             SAGE SDEPT
---------- -------------------- ---------- ---------- --------------------
         1 XiaoHong             Male               18 CS
         2 XiaoHua              Female             22 CS
         3 XiaoLan              Female             20 MA
         4 XiaoLi               Male               19 IS
         5 XiaoZhang            Male               18 IS
分享到:
评论

相关推荐

    Oracle笔记Oracle笔记

    Oracle笔记Oracle笔记Oracle笔记Oracle笔记Oracle笔记Oracle笔记

    oracle笔记数据处理

    oracle笔记数据处理,oracle中增加数据,删除数据,修改数据,回滚,提交,设置保存点等等知识点,有具体详细的代码案例!

    ORACLE DBA工作笔记 运维数据迁移与性能调优

    ORACLE DBA工作笔记 运维数据迁移与性能调优 清晰版 。。。

    oracle笔记异常处理

    oracle笔记异常处理,异常处理的代码案例和知识点笔记!

    Oracle笔记

    这个是我学习网上的视频做的oracle笔记,对于oracle一窍不通的菜鸟可能有用吧,大家有需要可以看看

    Oracle学习笔记(事务知识点)

    Oracle学习笔记(事务知识点),事务处理:所谓的事务处理其实就是保证数据操作的完整性,所有的操作要么同时成功,要么同时失败

    Oracle学习笔记

    Oracle学习笔记Oracle学习笔记Oracle学习笔记Oracle学习笔记Oracle学习笔记Oracle学习笔记Oracle学习笔记Oracle学习笔记Oracle学习笔记Oracle学习笔记Oracle学习笔记Oracle学习笔记Oracle学习笔记

    韩顺平oracle笔记(免费)

    韩顺平oracle笔记(免费)韩顺平oracle笔记(免费)

    oracle笔记创建和管理表

    oracle笔记创建和管理表,增加列,删除列,修改列,修改列名和数据类型和长度,修改表名等等操作,有代码案例!

    oracle经典笔记

    oracle经典笔记oracle经典笔记oracle经典笔记oracle经典笔记oracle经典笔记oracle经典笔记

    oracle千万级别数据简单操作

    oracle千万级别数据简单操作

    oracle 在java中的事务处理和异常回滚。

    oracle 在java中的事务处理和异常回滚。 里面的类直接运行,需要把oracle的数据库连接改改就ok、

    Oracle学习笔记 PDF

    本文档主要是网易云李兴华老师进行授课时所作笔记,从Oracle11g数据库的安装到复杂查询做了详细的文档记录。

    史上最全的oracle笔记

    初学Oracle 最最需要的东东 史上最全的oracle笔记

    oracle笔记过滤和排序数据

    oracle笔记,数据的过滤和排序!数据排序和过滤的相关语法,案例,注意事项等!

    oracle adg安装个人笔记

    oracle adg安装个人笔记oracle adg安装个人笔记oracle adg安装个人笔记oracle adg安装个人笔记oracle adg安装个人笔记oracle adg安装个人笔记oracle adg安装个人笔记oracle adg安装个人笔记oracle adg安装个人笔记...

    java Oracle事务处理

    java 代码写的关于Oracle的 事务处理

    oracle笔记.docx

    oracle学习笔记,包括oracle常用的语法和个人总结。

    Oracle 入门文档2

    Oracle笔记 七、PL/SQL 异常处理 Oracle笔记 八、PL/SQL跳转/判断/循环语句块 Oracle笔记 九、PL/SQL 游标的使用 Oracle笔记 十、PL/SQL存储过程 Oracle笔记 十一、PL/SQL函数和触发器 Oracle笔记 十二、PL/SQL...

Global site tag (gtag.js) - Google Analytics