zoukankan      html  css  js  c++  java
  • oralce中的dual详解 转 http://blog.sina.com.cn/s/blog_a5a24bcb0100zeay.html

    dual是属于sys的
    只有一个X varchar2(1)列
    查询虚拟列不会产生逻辑IO
    =======================================================================
    DUAL表的用途
    Dual 是 Oracle中的一个实际存在的表,任何用户均可读取,常用在没有目标表的Select语句块中

    --查看当前连接用户
    SQL> select user from dual;
    USER
    --------
    SYSTEM
    --查看当前日期、时间
    sql> select sysdate from dual;
    SYSDATE
    ---------
    2012-5-22
    sql> select to_char(sysdate,''yyyy-mm-dd hh24:mi:ss'') from dual;
    TO_CHAR(SYSDATE,''YYYY-MM-DDHH2
    ------------------------------
    2007-01-24 15:02:47
    --当作计算器用
    SQL> select 1+2 from dual;
    1+2
    ----------
    3
    --查看序列值
    SQL> create sequence aaa increment by 1 start with 1;
    SQL> select aaa.nextval from dual;
    NEXTVAL
    ----------
    1
    SQL> select aaa.currval from dual;
    CURRVAL
    ----------
    1
    =======================================================================
    关于DUAL表的测试与分析
      DUAL就是个一行一列的表,如果你往里执行insert、delete、truncate 操作,
    就会导致很多程序出问题。结果也因sql*plus、pl/sql dev等工具而异。
    =======================================================================
    查看DUAL是什么OBJECT
    DUAL是属于SYS schema的一个表, 然后以PUBLIC SYNONYM的方式供其他数据库USER使用
    SQL> select owner, object_name , object_type from dba_objects where object_name like '%DUAL%';

    OWNER OBJECT_NAME OBJECT_TYPE
    ---- ------------ ------------------
    SYS     DUAL       TABLE
    PUBLIC  DUAL       SYNONYM
     
    --查看表结构,只有一个字段DUMMY,为VARCHAR2(1)型
    SQL> desc dual
    Name Type Nullable Default Comments
    ----- ----------- -------- ------- --------
    DUMMY VARCHAR2(1) Y

    --DUAL表的结构:
    CREATE TABLE "SYS"."DUAL"
    (
    "DUMMY" VARCHAR2(1)
    )
    PCTFREE 10
    PCTUSED 40
    INITRANS 1
    MAXTRANS 255
    NOCOMPRESS LOGGING
    STORAGE(
        INITIAL 16384
        NEXT 1048576
        MINEXTENTS 1
        MAXEXTENTS 2147483645
      PCTINCREASE 0
      FREELISTS 1
      FREELIST GROUPS 1
      BUFFER_POOL DEFAULT)
    TABLESPACE "SYSTEM"
      DUAL表是建立在SYSTEM表空间的,第一是因为DUAL表是SYS这个用
    户建的,本来默认的表空间就是SYSTEM;第二,把这个可能经常被查询的表
    和用户表分开来存放,对于系统性能的是有好处的。
      有了创建了表、创建了同义词还是不够的。DUAL在SYS这个Schema下面,
    因此用别的用户登录是无法查询这个表的,因此还需要授权:
      grant select on SYS.DUAL to PUBLIC with grant option;
      将Select 权限授予公众。
      事实上,DUAL表中的数据和ORACLE数据库环境有着十分重要的关系(ORACLE不会为此瘫痪,但是不少存储过程以
    及一些查询将无法被正确执行)。
    =======================================================================
    DUAL 表行数问题
    SQL> select count(*) from dual;
    COUNT(*)
    ----------
    1
     
    SQL> select * from dual;
    DUMMY
    -----
    X
     
    --插入数据,再查询记录,只返回一行记
    SQL> insert into dual values ('Y');
    1 row created.
    SQL> commit;
    Commit complete.
    SQL> insert into dual values ('X');
    1 row created.
    SQL> insert into dual values ('Z');
    1 row created.
    SQL> commit;
    Commit complete.
    SQL> select count(*) from dual;
    COUNT(*)
    ----------
    4
    SQL> select * from dual;
    DUMMY
    -----
    X        --这里查就剩下一行数据了
    ----------------------------------------------------------------------------
    SQL> insert into dual values(''Y'');
    1 行 已插入
    SQL> commit;
    提交完成
    SQL> select * from dual;
    DUMMY
    -----
    X
    Y
    SQL> select sysdate from dual;
    SYSDATE
    -----------
    2012-5-22
    2012-5-22

    这个时候返回的是两条记录,这样同样会引起问题。在通过使用
    SQL>select sysdate into v_sysdate from dual;
    来获取时间或者其他信息的存储过程来说 ,ORACLE 会抛出TOO_MANY_ROWS(ORA-01422)异常。
    ----------------------------------------------------------------------------
    --把表截掉
    SQL> truncate table dual;
    Table truncated.
    SQL> select count(*) from dual;
    COUNT(*)
    ----------
    0
    SQL> select * from dual;
    no rows selected
    SQL> select sysdate from dual;
    no rows selected
    --试着把DUAL表中的数据删除,看看会出现什么结果:
    SQL> delete from dual;
    1 行 已删除
    SQL> select * from dual;
    DUMMY
    -----
    SQL> select sysdate from dual;
    SYSDATE
    -----------
     
      我们便取不到系统日期了。因为,sysdate是个函数,作用于每一个数据行。现在没有数据了,自然就不可能取出系统日期。
     
      这个对于很多用:
    SQL>select sysdate into v_sysdate from dual;
      这种方式取系统时间以及其他信息的存储过程来说是致命的,因为,
    ORACLE会马上抛出一个NO_DATA_FOUND(ORA-01403)的异常,即使异常
    被捕获,存储过程也将无法正确完成要求的动作。
    ----------------------------------------------------------------------------
      对于delete操作来说,oracle对dual表的操作做了一些内部处理,尽量保证dual表中只返回一条记录,
    当然这些内部操作是不可见的
      不管表内有多少记录(没有记录除外),oracle对于每次delete操作都只删除一条数据。
     SQL> select count(*) from dual;
    COUNT(*)
    ----------
    2
    SQL> delete from dual;
    1 行 已删除
    SQL> commit;
    提交完成
    SQL> select count(*) from dual;
    COUNT(*)
    ----------
    1
    =======================================================================
    Drop Dual table
      DUAL表可以执行插入、更新、删除操作,还可以执行drop操作。但是不要去执行drop表的操作,否则会使系统
    不能用,数据库起不了,会报Databasestartup crashes with ORA-1092错误。

    DUAL表被"不幸"删除后的恢复:
    (1)用sys用户登陆。
    SQL> create pfile=‘d:pfile.bak‘ from spfile
    SQL> shutdown immediate   
    (2)创建DUAL表。
      CREATE TABLE "SYS"."DUAL"
    (
    "DUMMY" VARCHAR2(1)
    )
    PCTFREE 10
    PCTUSED 40
    INITRANS 1
    MAXTRANS 255
    NOCOMPRESS LOGGING
    STORAGE(
        INITIAL 16384
        NEXT 1048576
        MINEXTENTS 1
        MAXEXTENTS 2147483645
      PCTINCREASE 0
      FREELISTS 1
      FREELIST GROUPS 1
      BUFFER_POOL DEFAULT)
    TABLESPACE "SYSTEM" ;
    (3)授予公众SELECT权限(SQL如下,但不要给UPDATE,INSERT,DELETE权限)
    sql> grant select on dual to Public;
    sql> select * from dual;
    (4)向DUAL表插入一条记录(仅此一条): insert into dual values('X');
    sql> insert into dual values(?X‘);
    (5)提交修改。
    sql> commit;

    最后:
    SQL> shutdown immediate
    SQL> startup
    --OK, 下面就可以正常使用了。

  • 相关阅读:
    总结:关于作用域的经典面试题
    解决JS拖拽出现的问题
    JS正则(3)总结
    JS正则(2)对正则的理解
    JS 闭包 正则(1)
    JS Date对象
    笔记
    9.13笔记
    9.12学习笔记
    9.11学习笔记
  • 原文地址:https://www.cnblogs.com/cb1186512739/p/9900137.html
Copyright © 2011-2022 走看看