Oracle数据库数据对象分析
Oracle数据库数据对象中最基本的是表和视图,其他还有约束、序列、函数、存储过程、包、触发器等。对数据库的操作可以基本归结为对数据对象的操作,理解和掌握Oracle数据库对象是学习Oracle的捷径。
表和视图
Oracle中表是数据存储的基本结构。ORACLE8引入了分区表和对象表,ORACLE8i引入了临时表,使表的功能更强大。视图是一个或多个表中数据的逻辑表达式。本文我们将讨论怎样创建和管理简单的表和视图。
管理表
表可以看作有行和列的电子数据表,表是关系数据库中一种拥有数据的结构。用CREATE TABLE语句建立表,在建立表的同时,必须定义表名,列,以及列的数据类型和大小。例如:
CREATE TABLE products (
PROD_ID NUMBER(4),
PROD_NAME VAECHAR2(20),
STOCK_QTY NUMBER(5,3)
);
这样我们就建立了一个名为products的表, 关键词CREATE TABLE后紧跟的表名,然后定义了三列,同时规定了列的数据类型和大小。
在创建表的同时你可以规定表的完整性约束,也可以规定列的完整性约束,在列上普通的约束是NOT NULL,关于约束的讨论我们在以后进行。
在建立或更改表时,可以给表一个缺省值。缺省值是在增加行时,增加的数据行中某一项值为null时,oracle即认为该值为缺省值。
下列数据字典视图提供表和表的列的信息:
. DBA_TABLES
. DBA_ALL_TABLES
. USER_TABLES
. USER_ALL_TABLES
. ALL_TABLES
. ALL_ALL_TABLES
. DBA_TAB_COLUMNS
. USER_TAB_COLUMNS
. ALL_TAB_COLUMNS
表的命名规则
表名标识一个表,所以应尽可能在表名中描述表,oracle中表名或列名最长可以达30个字符串。表名应该以字母开始,可以在表名中包含数字、下划线、#、$等。
从其它表中建立表
可以使用查询从基于一个或多个表中建立表,表的列的数据类型和大小有查询结果决定。建立这种形式的表的查询可以选择其他表中所有的列或者只选择部分列。在CREATE TABLE语句中使用关键字AS,例如:
SQL> CREATE TABLE emp AS SELECT * FROM employee
SQL> CREATE TABLE Y AS SELECT * FROM X WHERE no=2
需要注意的是如果查询涉及LONG数据类型,那么CREATE TABLE....AS SELECT....将不会工作。
更改表定义
在建立表后,有时候我们可能需要修改表,比如更改列的定义,更改缺省值,增加新列,删除列等等。ORACLE使用ALTER TABLE语句来更改表的定义
1、增加列
语法:ALTER TABLE [schema.] table_name ADD column_definition
例:
ALTER TABLE orders ADD order_date DATE;
对于已经存在的数据行,新列的值将是NULL.
2、更改列
语法: ALTER TABLE [schema.] table_name MODIFY column_name new_attributes;
例:
ALTER TABLE orders MODITY (quantity number(10,3),status varchar2(15));
这个例子中我们修改了表orders,将STATUS列的长度增加到15,将QUANTITY列减小到10,3;
修改列的规则如下:
. 可以增加字符串数据类型的列的长度,数字数据类型列的精度。
. 减少列的长度时,该列应该不包含任何值,所有数据行都为NULL.
. 改变数据类型时,该列的值必须是NULL.
. 对于十进制数字,可以增加或减少但不能降低他的精度。
3、删除数据列
优化ORACLE数据库,唯一的方法是删除列,重新建立数据库。在ORACLE8i中有很多方法删除列,你可以删除未用数据列或者可以标示该列为未用数据列然后删除。
语法:ALTER TABLE [schema.] table_name DROP {COLUM column_names | (column_names)}[CASCADE CONSTRAINS]
要注意的是在删除列时关于该列的索引和完整性约束也同时删除。注意关键字CASCADE CONSTRAINS,如果删除的列是多列约束的一部分,那么这个约束条件相对于其他列也同时删除。
如果用户担心在大型数据库中删除列要花太多时间,可以先将他们标记为未用数据列,标记未用数据列的语法如下:
ALTER TABLE [schema.] table_name SET UNUSED {COLUM column_names | (column_names)}[CASCADE CONSTRAINS]
这个语句将一个或多个数据列标记为未用数据列,但并不删除数据列中的数据,也不释放占用的磁盘空间。但是,未用数据列在视图和数据字典中并不显示,并且该数据列的名称将被删除,新的数据列可以使用这个名称。基于该数据列的索引、约束,统计等都将被删除。
删除未用数据列的语句是:
ALTER TABLE [schema.] table_name DROP {UNUSED COLUM | COLUMN CONTINUE}
删除表和更改表名
删除表非常简单,但它是一个不可逆转的行为。
语法: DROP TABLE [schema.] table_name [CASCADE CONSTRAINTS]
删除表后,表上的索引、触发器、权限、完整性约束也同时删除。ORACLE不能删除视图,或其他程序单元,但oracle将标示他们无效。如果删除的表涉及引用主键或唯一关键字的完整性约束时,那么DROP TABLE语句就必须包含CASCADE CONSTRAINTS子串。
更改表名
RENAME命令用于给表和其他数据库对象改名。ORACLE系统自动将基于旧表的完整性约束、索引、权限转移到新表中。ORACLE同时使所有基于旧表的数据库对象,比如视图、程序、函数等,为不合法。
语法:RENAME old_name TO new_name;
例:
SQL> RENAME orders TO purchase_orders;
截短表
TRUNCATE命令与DROP命令相似, 但他不是删除整个数据表,所以索引、完整性约束、触发器、权限等都不会被删除。缺省情况下将释放部分表和视图空间,如果用户不希望释放表空间,TRUNCATE语句中要包含REUSE STORAGE子串。TRUNCATE命令语法如下:
TRUNCATE {TABLE|CLUSTER} [schema.] name {DROP|REUSE STORAGE}
例:
SQL> TRUNCATE TABLE t1;
管理视图
视图是一个或多个表中的数据的简化描述,用户可以将视图看成一个存储查询(stored query)或一个虚拟表(virtual table).查询仅仅存储在oracle数据字典中,实际的数据没有存放在任何其它地方,所以建立视图不用消耗其他的空间。视图也可以隐藏复杂查询,比如多表查询,但用户只能看见视图。视图可以有与他所基于表的列名不同的列名。用户可以建立限制其他用户访问的视图。
建立视图
CREATE VIEW命令创建视图,定义视图的查询可以建立在一个或多个表,或其他视图上。查询不能有FOR UPDATE子串,在早期的ORACLE8i版本中不支持ORDER BY子串,现在的版本中CREATE VIEW可以拥有ORDER BY子串。
例:
SQL> CREATE VIEW TOP_EMP AS
SELECT empno EMPLOYEE_ID,ename EMPLOYEE_NAME,salary
FROM emp
WHERE salary > 2000
用户可以在创建视图的同时更改列名,方法是在视图名后立即加上要命名的列名。重新定义视图需要包含OR REPLACE子串。
SQL> CREATE VIEW TOP_EMP(EMPLOYEE_ID,EMPLOYEE_NAME,SALARY) AS
SELECT empno ,ename ,salary FROM emp WHERE salary >2000
如果在创建的视图包含错误在正常情况下,视图将不会被创建。但如果你需要创建一个带错误的视图必须在CREATE VIEW语句中带上FORCE选项。如:
CREATE FORCE VIEW ORDER_STATUS AS
SELECT * FROM PURCHASE_ORDERS
WHERE STATUS="APPPOVE";
SQL>/
warning :View create with compilation errors
这样将创建了一个名为ORDER_STATUS的视图,但这样的视图的状态是不合法的,如果以后状态发生变化则可以重新编译,其状态也变成合法的。
从视图中获得数据
从视图中获得数据与从表中获得数据基本一样,用户可以在连接和子查询中使用视图,也可以使用SQL函数,以及所有SELECT语句的字串。
插入、更新、删除数据
用户在一定的限制条件下可以通过视图更新、插入、删除数据。如果视图连接多个表,那么在一个时间里只能更新一个表。所有的能被更新的列可以在数据字典USER_UPDATETABLE_COLUMNS中查到。
用户在CREATE VIEW中可以使用了WITH子串。WITH READ ONLY子串表示创建的视图是一个只读视图,不能进行更新、插入、删除操作。WITH CHECK OPTION表示可以进行插入和更新操作,但应该满足WHERE子串的条件。这个条件就是创建视图WHERE子句的条件,比如在上面的例子中用户创建了一个视图TOP_EMP,在这个视图中用户不能插入salary小于2000的数据行。
删除视图
删除视图使用DROP VIEW命令。同时将视图定义从数据字典中删除,基于视图的权限也同时被删除,其他涉及到该视图的函数、视图、程序等都将被视为非法。
例:
DROP VIEW TOP_EMP;
过程和函数
过程和函数都以编译后的形式存放在数据库中,函数可以没有参数也可以有多个参数并有一个返回值。过程有零个或多个参数,没有返回值。函数和过程都可以通过参数列表接收或返回零个或多个值,函数和过程的主要区别不在于返回值,而在于他们的调用方式。过程是作为一个独立执行语句调用的:
pay_involume(invoice_nbr,30,due_date);
函数以合法的表达式的方式调用:
order_volumn:=open_orders(SYSDATE,30);
创建过程的语法如下:
CREATE [ OR REPLACE] PROCEDURE [schema.]procedure_name
[parameter_lister]
{AS|IS}
declaration_section
BEGIN
executable_section
[EXCEPTION
exception_section]
END [procedure_name]
每个参数的语法如下:
paramter_name mode datatype [(:=|DEFAULT) value]
mode有三种形式:IN、OUT、INOUT。
IN表示在调用过程的时候,实际参数的取值被传递给该过程,形式参数被认为是只读的,当过程结束时,控制会返回控制环境,实际参数的值不会改变。
OUT在调用过程时实际参数的取值都将被忽略,在过程内部形式参数只能是被赋值,而不能从中读取数据,在过程结束后形式参数的内容将被赋予实际参数。
INOUT这种模式是IN和OUT的组合;在过程内部实际参数的值会传递给形式参数,形势参数的值可读也可写,过程结束后,形势参数的值将赋予实际参数。
创建函数的语法和过程的语法基本相同,唯一的区别在于函数有RETUREN子句
CREATE [ OR REPLACE] FINCTION [schema.]function_name
[parameter_list]
RETURN returning_datatype
{AS|IS}
declaration_section
BEGIN
executable_section
[EXCEPTION]
exception_section
END [procedure_name]
在执行部分函数必须有哟个或多个return语句。
在创建函数中可以调用单行函数和组函数,例如:
CREATE OR REPLACE FUNCTION my_sin(DegreesIn IN NUMBER)
RETURN NUMBER
IS
pi NUMBER=ACOS(-1);
RadiansPerDegree NUMBER;
BEGIN
RadiansPerDegree=pi/180;
RETURN(SIN(DegreesIn*RadiansPerDegree));
END;
包
包是一种将过程、函数和数据结构捆绑在一起的容器;包由两个部分组成:外部可视包规范,包括函数头,过程头,和外部可视数据结构;另一部分是包主体(package body),包主体包含了所有被捆绑的过程和函数的声明、执行、异常处理部分。
打包的PL/SQL程序和没有打包的有很大的差异,包数据在用户的整个会话期间都一直存在,当用户获得包的执行授权时,就等于获得包规范中的所有程序和数据结构的权限。但不能只对包中的某一个函数或过程进行授权。包可以重载过程和函数,在包内可以用同一个名字声明多个程序,在运行时根据参数的数目和数据类型调用正确的程序。
创建包必须首先创建包规范,创建包规范的语法如下:
CREATE [OR REPLACE] PACKAGE package_name
{AS|IS}
public_variable_declarations |
public_type_declarations |
public_exception_declarations |
public_cursor_declarations |
function_declarations |
procedure_specifications
END [package_name]
创建包主体使用CREATE PACKAGE BODY语句:
CREATE [OR REPLACE] PACKAGE BODY package_name
{AS|IS}
private_variable_declarations |
private_type_declarations |
private_exception_declarations |
private_cursor_declarations |
function_declarations |
procedure_specifications
END [package_name]
私有数据结构是那些在包主体内部,对被调用程序而言是不可见的。
触发器(Triggers)
触发器是一种自动执行响应数据库变化的程序。可以设置为在触发器事件之前或之后触发或执行。能够触发触发器事件的事件包括下面几种:
DML事件
DDL事件
数据库事件
创建触发器的语法如下:
CREATE [OR REPLACE] TRIGGER trigger_name
{before|after|instead of} event
ON {table_or_view_name|DATABASE}
[FOR EACH ROW[WHEN condition>
trigger_body
只有DML触发器(INSERT、UPDATE、DELETE)语句可以使用INSTEAD OF触发器并且只有表的DML触发器可以是BEFORE或AFTER触发器。
象约束一样触发器可以被设置为禁用或启用来关闭或打开他们的执行体(EXECUTE),将触发器设置为禁用或启用使用ALTER TRIGGER语句:
ALTER TRIGGER trigger_name ENABLE;
ALTER TRIGGER trigger_name DISABLE;
要禁用或启用表的所有触发器,使用ALTER TABLE语句
ALTER TRIGGER table_name DISABLE ALL TRIGGER;
ALTER TRIGGER table_name ENABLE ALL TRIGGER;
删除触发器使用DROP TRIGGER
DROP TRIGGER trigger_name;
数据字典
Oracle数据字典包含了用户数据库的元数据。带下划线的表名称中带OBJ$、UET$、SOURCE$,这些表是在执行CREATE DATABASE语句期间由sql.bsq脚本创建的,一般情况下用户很少访问这些表。脚本catalog.sql(通常位于$oracle_home/rdbms/admin)在CREATE DATABASE语句之后立即运行,创建数据字典视图。
数据字典视图大致可以分为三类:
.前缀为USER_的数据字典视图,包含了用户拥有的对象的信息。
.前缀为ALL_的数据字典视图,包含了用户当前可以访问的全部对象和权限的信息。
.前缀为DBA_的数据字典视图,包含了数据库拥有的所有对象和权限的信息。
在绝大多数数据字典视图中都有象DBA_TABLES,ALL_TABLES和USER_TABLES这样的视图家族。Oracle中有超过100个视图家族,所以要全面介绍这些视图家族是单调乏味的而且没有多大的意义。在下表中列出了最重要和最常用的视图家族,需要注意的是每个视图家族都有一个DBA_,一个ALL_一个USER_视图。
其他的字典视图中主要的是V$视图,之所以这样叫是因为他们都是以V$或GV$开头的。V$视图是基于X$虚拟视图的。V$视图是SYS用户所拥有的,在缺省状况下,只有SYS用户和拥有DBA系统权限的用户可以看到所有的视图,没有DBA权限的用户可以看到USER_和ALL_视图,但不能看到DBA_视图。与DBA_,ALL,和USER_视图中面向数据库信息相反,这些视图可视的给出了面向实例的信息。
在大型系统上化几周时间手工输入每一条语句
手工输入带用户名变量的语句,然后再输入每一个用户名,这需要花好几个小时的时间
写一条SQL语句,生成需要的ALTER USER语句,然后执行他,这只需要几分钟时间
很明显我们将选择生成SQL的方法:
例:
SELECT "ALTER USER"||username||"TEMPORARY TABLESPACE temp;"
FROM DBA_USERS
WHERE username<>"SYS"
AND temporary_tablespace<>"TEMP";
这个查询的结果将被脱机处理到一个文件中,然后在执行:
ALTER USER SYSTEM TEMPORARY TABLESPACE temp;
ALTER USER OUTLN TEMPORARY TABLESPACE temp;
ALTER USER DBSNMP TEMPORARY TABLESPACE temp;
ALTER USER SCOTT TEMPORARY TABLESPACE temp;
ALTER USER DEMO TEMPORARY TABLESPACE temp;