`
changhongbao
  • 浏览: 123993 次
  • 性别: 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 数据库的基本概念、SQL 语句、数据查询、数据更新操作、事务处理操作、数据表的定义与管理、约束的设置、数据伪列的使用、SQL Developer 工具的使用等知识...

    oracle 学习笔记

    1. Rownum是Oracle数据库中用于表示查询结果集中行号的一个伪列。 2. Rownum在SQL中使用时有一些特殊的行为,特别是在带有子查询时。 3. Where rownum的执行过程与直接写5的执行过程不同。 4. Rownum=5的执行可能...

    oracle笔记 (导出、导入、创建用户、授权、insert,rownum)

    Oracle数据库是全球广泛使用的大型关系型数据库管理系统,其在数据管理、事务处理和企业级应用中扮演着核心角色。本文将深入探讨Oracle笔记中的几个关键概念:导出、导入、创建用户、授权以及使用INSERT语句和ROWNUM...

    oracle最全学习笔记(个人总结)

    ### Oracle 最全学习笔记知识点梳理 #### 一、存储过程 - **定义**:存储过程是一种在数据库中存储复杂程序以便外部程序调用的一种数据库对象。 - **应用场景**:主要用于执行大量的更新或插入操作,以提高数据库...

    达内-ORACLE学习笔记

    Oracle提供了丰富的内置函数,用于处理各种数据类型,提高数据处理的灵活性和效率。 - **字符函数**:如UPPER、LOWER、CONCAT等,用于转换和组合字符串。 - **数值函数**:如ROUND、TRUNC、MOD等,用于数学运算。 -...

    oracle11gR2学习笔记

    在Oracle中实现分页查询,可以结合ROWNUM伪列,如上述示例所示,先创建一个带有ROWNUM的新表,然后根据ROWNUM进行筛选,实现数据分页。 这些只是Oracle 11g R2学习笔记中的部分内容,实际学习和使用中还会涉及更多...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 第一章 Oracle入门 一、 数据库概述 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今五十年前。简单来说是本身可视...

    全套java笔记数据库部分

    6. "2015081303_数据伪列.doc":数据伪列是Oracle特有的功能,可能涉及虚拟列、序列或隐藏列等概念。 7. "2015081103_分组统计查询.doc":介绍了SQL中的GROUP BY语句和聚合函数,如COUNT、SUM、AVG等,用于数据的...

    Redis学习资料的完整笔记

    - **伪事务**:Redis中的事务并非传统意义上的ACID事务,而是一组命令的序列。这些命令被放到一个队列中,在事务结束时统一执行。 - **开启事务**:使用`MULTI`命令开启事务。 - **执行命令**:在事务开启后,使用...

    我的学习笔记 ,涵盖:C#,java,SqlServer,MySql,Oracle,HTML,CSS.zip

    5. **Oracle**:Oracle是企业级的数据库系统,提供强大的数据管理功能。其关键知识点包括PL/SQL编程、表空间与数据文件、索引类型、分区表、游标、存储过程、触发器、备份与恢复、性能监控等。 6. **HTML**:HTML是...

    db2学习笔记(个人总结)

    Oracle数据库提供了`ROWNUM`伪列进行分页,其用法如下: ```sql SELECT * FROM ( SELECT a.*, ROWNUM rnum FROM 表名 a ) WHERE rnum BETWEEN (pageNo-1)*pageSize+1 AND pageNo*pageSize; ``` 这里的`pageNo`是...

Global site tag (gtag.js) - Google Analytics