发布新日志

  • [转]Oracle中自增字段的两种方法的比较(Trigger和Sequence)

    2007-07-01 16:28:14

    在ORACLE中,没有象MS-SQLSERVER中那样子有自增字段,但是如果我们要实现这个功能,有2种方法

    1 Trigger

    sql语句如下:

    create or replace trigger trigger_name
    before insert on your_sid.tablename
    for each row
    begin

    declare
    i number;
    cursor cur is select max(id) from your_sid.tablename;

    BEGIN
    open cur;

    FETCH cur INTO i;

    if i is NULL then
    :new.id := 0;  //可以根据实际需要来定初始值
    else
    :new.id := i + 1; //这里以1递增
    end if;

    Close cur;
    END;

    END;
    /

    其中:your_sid为数据库的当前用户SID,tablename为表名,id为列名,

    2 Sequence

    sql语句如下:

    create sequence your_sid.sequence_name
    increment by 1  //指定序列以1递增,如果没指定,默认值1会使用
    start with 1        //由1开始计数
    nomaxvalue     //不设置最大值
    minvalue 1      //设置最小值1
    cache 20        //预分配缓存大小为20
    order

    二者的区别在于,Sequence的效率要比Trigger的高,因为Trigger每次都要遍历表中所有记录以寻找ID最大值,而Sequence每次执行后,都会保留最大值;

  • [转]什么情况下应建立索引

    2007-06-11 09:15:38

    什么情况下应该建立索引

    表的主关键字
    自动建立唯一索引
    如zl_yhjbqk(用户基本情况)中的hbs_bh(户标识编号)

    表的字段唯一约束
    ORACLE利用索引来保证数据的完整性
    如lc_hj(流程环节)中的lc_bh+hj_sx(流程编号+环节顺序)

    直接条件查询的字段
    在SQL中用于条件约束的字段
    如zl_yhjbqk(用户基本情况)中的qc_bh(区册编号)
    select * from zl_yhjbqk where qc_bh=’<????甼曀???>7001’

    查询中与其它表关联的字段
    字段常常建立了外键关系
    如zl_ydcf(用电成份)中的jldb_bh(计量点表编号)
    select * from zl_ydcf a,zl_yhdb b where a.jldb_bh=b.jldb_bh and b.jldb_bh=’540100214511’

    查询中排序的字段
    排序的字段如果通过索引去访问那将大大提高排序速度
    select * from zl_yhjbqk order by qc_bh(建立qc_bh索引)
    select * from zl_yhjbqk where qc_bh=’7001’ order by cb_sx(建立qc_bh+cb_sx索引,注:只是一个索引,其中包括qc_bh和cb_sx字段)

    查询中统计或分组统计的字段
    select max(hbs_bh) from zl_yhjbqk
    select qc_bh,count(*) from zl_yhjbqk group by qc_bh

    什么情况下应不建或少建索引

    表记录太少

    如果一个表只有5条记录,采用索引去访问记录的话,那首先需访问索引表,再通过索引表访问数据表,一般索引表与数据表不在同一个数据块,这种情况下ORACLE至少要往返读取数据块两次。而不用索引的情况下ORACLE会将所有的数据一次读出,处理速度显然会比用索引快。

    如表zl_sybm(使用部门)一般只有几条记录,除了主关键字外对任何一个字段建索引都不会产生性能优化,实际上如果对这个表进行了统计分析后ORACLE也不会用你建的索引,而是自动执行全表访问。如:

    select * from zl_sybm where sydw_bh=’5401’(对sydw_bh建立索引不会产生性能优化)

    经常插入、删除、修改的表
    对一些经常处理的业务表应在查询允许的情况下尽量减少索引,如zl_yhbm,gc_dfss,gc_dfys,gc_fpdy等业务表。

    数据重复且分布平均的表字段
    假如一个表有10万行记录,有一个字段A只有T和F两种值,且每个值的分布概率大约为50%,那么对这种表A字段建索引一般不会提高数据库的查询速度。

    经常和主字段一块查询但主字段索引值比较多的表字段

     如gc_dfss(电费实收)表经常按收费序号、户标识编号、抄表日期、电费发生年月、操作标志来具体查询某一笔收款的情况,如果将所有的字段都建在一个索引里那将会增加数据的修改、插入、删除时间,从实际上分析一笔收款如果按收费序号索引就已经将记录减少到只有几条,如果再按后面的几个字段索引查询将对性能不产生太大的影响。

  • PL/SQL学习笔记(八)

    2007-06-07 11:11:53

    1. PL/SQL支持三类集合:

    索引表;嵌套表;变长数组

    2. 索引表是一个由元素组成的表,它被保存在内存中,其中每一个元素用一个整数值做索引。索引表的功能与数组类似,但有两个主要的区别:

    • 索引表可以稀疏地填充;
    • 不给索引表设置最大长度。

    3. 通过声明一个类型,然后声明一个或多个这种类型的变量来声明索引表。声明类型时,指定了集合的数据类型,并指定了表索引的数据类型。集合的数据类型可以是标量类型(如NUMBER或VARCHAR2)或复合类型(如记录)。表索引的数据类型必须是BINARY_INTEGER.声明索引表类型的语法如下:

    TYPE type_name IS TABLE OF data_type [NOT NULL] INDEX BY BINARY_INTEGER;

    4. 可以用table_name.EXISTS(index_num)来判断某个索引值对应的条目是否存在。

    5. 删除索引表中的条目:

    table_name.DELETE[(first_entry[,last_entry])];

    6. 在数据库中,嵌套表是一个无序记录集合。声明嵌套表类型的语法:

    TYPE type_name IS TABLE OF data_type (NOT NULL);

    如果需要PL/SQL专用数据类型(如BOOLEAN/NATUAL或INTEGER)的数组,则只能选择索引表。

    7. 给嵌套表添加条目与给索引表添加条目有些不同。必须使用构造函数初始化嵌套表后,才能给它添加条目。初始化嵌套表后,如果要增加表的大小,需要调用extend方法。

    构造函数的名称与声明表时使用的类型名称相同,例如:

    depts := dept_table();

    也可以在调用构造函数时,给它传递一个或多个条目的值,如

    depts := dept_table(dept1,dept2);

    8. 对于嵌套表,使用delete()方法删除条目后,exists()方法并不知道删除了一些条目,所以删除条目后工作区必须至少执行一次count()方法

    9. 声明变长数组类型的语法如下:

    TYPE type_name IS (VARRAY|VARYING ARRAY) (size) OF entry_type [NOT NULL];

    10. 批绑定让您编写对集合中所有条目进行操作的SQL语句,而不必使用PL/SQL代码在集合中循环。从SQL(取回数据)到PL/SQL(将数据添加到数组中)的切换被称为关联转换(context switch),这增加了许多开销。可以使用批绑定避免大部分这种开销。

    两个新关键字支持绑定。BULK COLLECT用于SELECT语句中,将所有的数据放到一个集合中;FORALL用于INSERT/UPDATE/DELETE语句中,以便对集合中的每一个元素执行这些语句一次。

    11. 可以在SELECT INTO语句和FETCH 语句中使用BULK COLLECT。(但是BULK COLLECT不能使用记录表)

    12. 关键字FORALL允许您将一条数据操纵语言(DML)语句(即INSERT/UPDATE或DELETE)基于一个集合的内容,使用FORALL时,该语句对集合中的每个条目执行一次,但从PL/SQL到SQL的关联转换只有一次,这使得性能比在PL/SQL中使用循环快的多。

  • PL/SQL学习笔记(七)

    2007-06-06 21:02:59

     1. Oracle游标是一种用于轻松地处理多行数据的机制。游标的另一项功能是,它包含一个跟踪当前访问的记录的指针,这使您的程序能够一次处理多条记录。

    2. 将游标放在一个FOR循环中,这种FOR循环被称为游标FOR循环。它显式地完成下述工作:

    声明循环索引;

    打开游标;

    每次循环迭代都取回游标的下一条记录;

    处理完所有的记录或退出循环时关闭游标

    如:

    DECLARE
      CURSOR all_depts
       is
        SELECT dept_id,dept_name
        FROM department
        ORDER BY dept_name;
       
      dept all_depts%ROWTYPE;
    BEGIN                      --implicit cursor open
      FOR dept in all_depts LOOP     --implicit cursor fetch
       
        DBMS_OUTPUT.PUT_LINE(dept.dept_name);
        DBMS_OUTPUT.PUT_LINE(all_depts%rowcount);
       
     
      END LOOP;            --implicit cursor close
      COMMIT;

    END;

    3. Oracle允许删除或更新当前的记录。要删除或更新取回的记录,必须使用FOR UPDATE子句声明游标,并且必须打开了游标。

    4. 游标变量B被赋值为游标变量A,游标变量A被赋值为游标对象123,两个游标变量都在游标对象的作用域内,当游标变量A被删除后,游标变量B仍然可以访问游标对象123。

    5. 隐式游标可用sql对象访问游标属性,如sql%rowcount,sql%found,etc

  • PL/SQL学习笔记(六)

    2007-06-05 23:38:22

    1. 一次插入两条数据的INSERT 语句示例:

    INSERT INTO employee (emp_id, emp_name)
    select 1,'Jessica Loraine' from dual union all
    select 2,'Kurt Roberts' from dual ;

    2. 声明记录变量:

    TYPE emp_pay_info IS RECORD

    (emp_id INTEGER,

    emp_name VARCHAR(32),

    pay_rate NUMBER(9,2),

    pay_type CHAR(1)

    );

    3. 如果使用的是记录,并且希望一些字段的定义与数据库表中列的定义相同,则可以用%TYPE属性(%TYPE可用于任何变量声明中,而不仅仅是记录中)

    variable_name table_name.column_name%TYPE;

    4. 可以使用%ROWTYPE属性声明一个基于表的记录

    table_name%ROWTYPE

    5. 伪列

    CURRVAL,NEXTVAL,ROWID,ROWNUM

    INSERT INTO employee

    VALUES (emp_id_seq.NEXTVAL, 'Stanton Bernard');

    ROWID伪列表示表中记录的二进制地址,可以用UROWID类型的变量以可读的格式存储rowid。

    ROWNUM伪列指出从表中检索数据的次序。

    6. 事务控制语句确保使用数据操纵语句时的数据完整性。即当使用SELECT/UPDATE/INSERT和DELETE语句时,程序员将插入合适的事务控制语句,以确保数据是准确的,并防止数据遭到破坏。

  • PL/SQL学习笔记(五)

    2007-06-05 22:45:00

    1. 包是一个封装的相关schema对象的集合。这些对象包括过程、函数、变量、常量、游标和异常。

    2. 包具有下述优点:

    使您能够更有效地将应用程序组织成模块。每个包都易于理解,包之间的接口简单、明了、定义完善

    允许您高效的授予权限

    在会话期间,包的公用变量和游标持续可用,因此所有的游标以及在这种环境中执行的过程可以共享它们。

    使您能够重载过程和函数

    通过一次将多个对象加载到内存中改善了性能,因此以后对包中相关子程序的调用不需要进行输入/输出操作。

    通过使用包含存储过程和函数的库,提高了代码的重用性,消除了重复性编码工作。

    3. 创建包的第一步是创建其规范,规范将在包体中定义的模式对象声明为公用的。

    创建包体:

    CREATE [OR REPLACE] PACKAGE BODY package_name {IS|AS}

    [package body object declaration]

    BEGIN

    programming statements

    END [package_name];

    4. 可以使用包含compile关键字的ALTER PACKAGE命令重新编译包。这种显式的重新编译消除了运行阶段的隐式重新编译,并防止了任何相关的运行阶段编译错误以及性能开销。通常在修改包后,显式地重新编译它。

    ALTER PACKAGE employee_maint compile body

    ALTER PACKAGE employee_maint compile package

    第一句只重新编译包体,第二条重新编译整个包,包括包体和规范

    5. 任何在包规范中声明的项目在包外都是可见的。这使得包外的PL/SQL代码能够引用包内的对象。在包规范中声明的对象被称为公有的;在包体中声明的对象只能在包中使用,因此包外PL/SQL块不能引用任何在包内私自声明的变量。

    6. 对于独立的过程,变量、游标和常量只在过程调用期间是持续的,当过程终止后,它们便消失了;如果变量、常量或游标是在包规范或者包体中声明的,则在用户的会话期间,它们的值是持续的;当当前用户的会话终止或重新编译包时,它们的值便消失。

    7. 包要么是有效的,要么是无效的。如果最后一次编译包后,其源代码和它引用对象没有被删除、替换或修改,则这个包被认为是有效的。如果最后一次编译包后,其源代码或它引用的对象被删除、替换或修改,则这个包被认为是无效的。

  • PL/SQL学习笔记(四)

    2007-06-04 11:59:47

    1. 当子程序使用参数列表中引用的变量或表达式调用函数时,这些参数被称为实参,在这种情况下,参数实际上将参数值保存在内存中;如果变量或表达式是在子程序规范中声明,并在子程序主体中引用时,则参数称为形参,在这种情况下,内存中保存的是指向真正的参数值的指针.

    2. 定义函数中的参数类型时,如果要接受一个来自表中的参数,并且不想对参数类型使用硬编码,因为以后可能会改变——只需在参数后面添加%TYPE,以便从表中获得字段类型即可。例如下面一行代码将参数p_emptype的数据类型设置为表employee中pay_type字段的类型

    (p_emptype employee.pay_type%TYPE)

    3. 当参数中包含大型值、表达式或记录时,将对性能造成极大的影响。将这些数据拷贝到参数中需要花费时间。程序员提高程序性能的一种方法是在模式语句中使用NOCOPY提示。

    使用NOCOPY提示时,您指导(而不是命令)编译器按引用(而不是按值)传递参数

    4. 存储函数是一个保存在数据库中的函数,可以被PL/SQL代码调用。函数和存储函数的唯一区别是,在关键字FUNCTION加上CREATE [OR REPLACE]关键字。

    5. 使用EDIT FUNCTION_NAME;修改函数代码后,必须将它重新装载到缓冲区中(GET FUNCTION_NAME),然后输入/并按回车执行

    6. 缺省情况下,函数执行时,其权限与函数的定义者相同,而不是调用者.定义者的权限受它所在的schema约束,您可以在PL/SQL完全限定对象名称,以便能够修改其他schema中的表.但是,这会限制您代码的移植性.

    Oracle允许您使用调用者权限调用函数.在这种情况下,您不受schema的约束,而是受调用者权限的约束。您可以通过AUTHID子句使用调用者权限,如:

    CREATE OR REPLACE FUNCTION mypi

      AUTHID CURRENT_USER AS

    BEGIN

      NULL;

      RETURN 3.14;

    END;

    7. ORACLE SCHEMA OBJECT的定义

    A schema is a collection of database objects. A schema is owned by a database user and has the same name as that user. Schema objects are logical structures created by users to contain, or reference, their data. Schema objects include structures like tables, views, and indexes. You can create and manipulate schema objects using Oracle Enterprise Manager.

  • PL/SQL学习笔记(三)

    2007-06-03 16:58:55

    1.在比较两个CHAR数据类型时,Oracle使用空白填补比较语义(blank-padded comparison semantics)。这意味着Oracle在较短的字符串的尾部概念性地填补足够的空格,使之与较长的字符串等长,然后进行比较,比较两个字符串常量时,Oracle也这么做,然而当其中一个值为变长字符串时,Oracle使用不填补比较语义(non-padded comparison semantics),因此字符串尾部的空格影响比较结果。

    2.三值逻辑真值表

    操作符         表达式           结果

    AND           TRUE AND TRUE     TRUE

                  TRUE AND FALSE    FALSE

                  TRUE AND NULL     NULL

                  FALSE AND NULL    FALSE

                  NULL AND NULL     NULL

    OR            TRUE OR TRUE      TRUE

                  TRUE OR FALSE     TRUE

                  TRUE OR NULL      TRUE

                  FALSE OR NULL     FALSE

                  NULL OR NULL      NULL 

    NOT           NOT TRUE          FALSE

                  NOT FALSE         TRUE 

                  NOT NULL          NULL

    3. 检查空值时一定要使用IS NULL 操作符,而不要使用相等或不等操作符比较变量和空值

    4. 当参数为空值时,内置函数NVL让您指定使用另一个值。语法类似于:

       NVL(expression, value_if_expression_is_null)

  • PL/SQL学习笔记(二)

    2007-06-01 15:45:40

    1. 比较CHAR字符串和VARCHAR2字符串时,应该像下面这样使用rtrim函数清除CHAR字符串后面的空格

    IF RTRIM(employee_name_c)=employee_name_v THEN_

    2. 可以使用trunc()函数裁剪日期DATE变量,使之不包含时间部分

  • PL/SQL学习笔记(一)

    2007-05-31 22:52:21

    1. PL/SQL是Oracle对SQL扩展的过程性语言,与SQL不同,PL/SQL是过程性的,而不是声明性的,这意味着代码规定了如何完成工作。

    2.使用dbms_output.put_line()来打印数据时,需要先用SET SERVEROUTPUT ON把服务器输出选项打开

    3.执行SQL*PLUS命令执行文件test.sql:

    SQL> @c:\a\test

    4.可以使用SHOW ERRORS命令查看错误的详细信息

    5.调用不带参数的函数必须确保不添加圆括号

    6.显示函数返回值可以使用:SELECT FUNC_NAME FROM DUAL;(DUAL时一个总是存在的特殊的Oracle表,它总是只有一行一列。从DUAL表中选择函数即可显示函数的结果)

    7.在过程生成器中执行PL/SQL时,需要把dbms_output.put_line替换为text_io.put_line(由于dbms_ouput是一个只存在于数据库服务器中的包),另外,和SQL*PLUS不同,不需要输入斜杠来告诉过程生成器已经输入完了PL/SQL块。

     

  • Oracle用户密码及权限相关Tips

    2007-05-31 22:06:11

    1.忘记密码时,可以用
    sqlplus /nolog
    conn / as sysdba
    startup (如果数据库不是处于启动状态则启动)
    alter user sys identified by abcdef
    然后就可以使用sys用户密码登陆了

    之后可以修改其他用户的密码。

    (或者用orapwd.exe命令,可以修改命令。
    orapwd file='/oracle/pwdsid.ora'  password=123456
    这个命令是修改sys用户的密码。你把生成的文件覆盖原来的密码文件。除sys和system其他用户的密码不会改变。没试验过)

    2.SQLPLUS下查看有哪些用户:
    select * from all_users;

    删除用户:
    DROP USER username CASCADE; //CASCADE为可选项
    创建用户:

    CREATE USER sidney
    IDENTIFIED BY welcome
    DEFAULT TABLESPACE cases_ts
    QUOTA 10M ON cases_ts
    QUOTA 5M ON temp_ts
    QUOTA 5M ON system
    PROFILE engineer
    PASSWORD EXPIRE;
    还有其它的关键字,可以查oracle的联机文档。

    3.如果出现user lacks create session privilege错误,可以用grant create to username;授予权限

    4.如果出现类似ORA-01950:表空间'SYSTEM'中无权限,可以用grant connect, rescource to username;授予权限

     

     

     

Open Toolbar