5.2 分类主要的数据库对象
数据库内有各种不同类型的对象,当前版本的对象比早期版本的对象更多。所有对象都有名称,所有的对象都由某人拥有。“某人”是一个数据库用户,例如HR,用户拥有的对象就是其模式。对象的名称必须遵循某些规则。
5.2.1 对象类型
下面这个查询列出了某个特定数据库中存在的对象类型,并计算有多少种:
SQL> select object_type, count(object_type) from dba_objects group by object_type order by object_type; OBJECT_TYPE COUNT(OBJECT_TYPE) OBJECT_TYPE COUNT(OBJECT_TYPE) ------------ ----------------- --------------- ------------------ CHAIN 1 PACKAGE 1321 CLUSTER 10 PACKAGE BODY 1259 CONSUMER GROUP 20 PROCEDURE 196 CONTEXT 10 PROGRAM 10 DESTINATION 2 QUEUE 30 DIMENSION 5 RESOURCE PLAN 13 DIRECTORY 14 RULE 3 EDITION 1 RULE SET 22 EVALUATION CONTEXT 16 SCHEDULE 4 FUNCTION 350 SCHEDULER GROUP 4 INDEX 4514 SEQUENCE 273 INDEX PARTITION 492 SYNONYM 37018 INDEXTYPE 8 TABLE 2603 JAVA CLASS 30942 TABLE PARTITION 408 JAVA DATA 325 TABLE SUBPARTITION 32 JAVA RESOURCE 979 TRIGGER 611 JAVA SOURCE 2 TYPE 2527 JOB 29 TYPE BODY 226 JOB CLASS 15 UNDEFINED 17 LIBRARY 224 UNIFIED AUDIT POLICY 7 LOB 921 VIEW 6189 LOB PARTITION 15 WINDOW 9 MATERIALIZED VIEW 2 XML SCHEMA 49 OPERATOR 55 47 rows selected.
这个查询从视图DBA_OBJECTS中检索对象,数据库中的每个对象都有一行。对象的种类很少,因为这个数据库很小,它只用于教学。商业应用程序使用的数据库可能有更多的对象。是否可以查看视图DBA_OBJECTS,取决于账户拥有的权限。另一种视图是USER_OBJECTS,它会显示用户拥有的所有对象;ALL_OBJECTS会显示用户能够访问的所有对象(包括用户拥有的对象)。所有用户都能访问这些视图。在12c 数据库中,新增的视图以CDB_作为前缀,提供了新的多租户数据库功能,该功能逻辑上把传统的数据库分隔为一个容器和可选的多个可插入数据库。
SQL编程人员最感兴趣的对象是包含或者能够访问数据的对象。它们是表、视图、同义词、索引和序列。
表以行和列的形式存储数据。视图是存储的SELECT语句,可以像表一样引用它。它仅仅是一个命名的查询,用户不是运行语句本身,而是对视图发出SELECT语句。实际上,用户是从另一个选择结果中进行选择。同义词是表(或视图)的别名。用户可以对同义词执行SQL语句,数据库将把它们映射成为针对同义词所指的对象执行的语句。索引可以减少对表中行的访问次数。如果查询只需要一行,那就不用扫描整个表来找到这一行,因为索引可以提供一个指向该行的确切位置的指针。当然,必须搜索索引本身,但这通常比扫描整个表要快。序列是一种生成唯一数字的结构。序列按要求有序地发出数字。
其余的对象类型并不是SQL编程人员所常用的,而是更多地被PL/SQL编程人员和数据库管理员使用。
5.2.2 用户和模式
许多人都互换地使用术语“用户”和“模式”。在Oracle环境中,可以不再这么使用(但其他数据库管理系统就不一定了)。用户是一个可以连接数据库的人,用户有用户名和密码,模式是包含用户所拥有对象的容器。创建用户时,其模式也就创建了。模式是用户拥有的对象,最初,模式是空的。
一些模式总是空的,用户永远不会创建任何对象,因为他们不需要创建对象,(如果设置正确)也没有必要的权限。这种用户会通过直接授权或者通过角色获得权限,以使用代码访问其他用户拥有的其他模式中的数据。其他用户可能与此相反,他们拥有许多对象,但从来不会登录数据库。他们甚至可能没有被授予CREATE SESSION权限,所以账户是禁用的(或者可以被锁定);这些模式用作其他人访问的代码和数据的资源库。
模式对象是有拥有者的对象。特定类型的对象的唯一标识符不是它的名称,而是在该名称的前面加上它所属模式的名称。因此,表HR.REGIONS指的是表REGIONS,由用户HR所有。还可能有另一个表SYSTEM. REGIONS,这是一个完全不同的表(也许结构和内容都不同),由用户SYSTEM所有,位于他的模式下。
在创建数据库时,会自动创建许多用户(及其相关的模式)。其中最重要的是SYS和SYSTEM。用户SYS拥有数据字典,数据字典是一组表(在SYS模式下),定义了数据库及其内容。SYS还拥有几百个PL/SQL包,它们包含的代码供数据库管理员和开发人员使用。SYS模式中的对象永远都不能用DML(数据操纵语言)命令修改。如果要对数据字典表执行DML,就可能破坏数据字典,造成灾难性后果。运行DDL命令(例如CREATE TABLE)可以更新数据字典,这会在我们和数据字典之间提供一个抽象层。SYSTEM模式存储各种用于管理和监控的附加对象。
根据数据库创建过程中选择的选项,可能会创建更多的用户。这些用户存储各种数据库选项需要的代码和数据。例如,用户MDSYS存储Spatial使用的对象,这个选项扩展了Oracle数据库的功能,使之能管理地理信息。
5.2.3 命名模式对象
模式对象归用户所有。所有模式对象的名称都必须符合一定规则:
● 名称可以是1~30个字符长(数据库链接名除外,它可以达到128个字符长)。
● 保留字(如SELECT)不能用作对象名称。
● 所有名称必须以A~Z的字母开头。
● 名称中的字符只能是字母、数字、下划线(_)、美元符号($)或者井字符号(#)。
● 小写字母将自动转换为大写字母。
通过将名称括在双引号内,所有这些规则(除长度之外)都可以打破,但在后面使用对象时,也一定要用双引号指定它,如图5-5的示例所示。注意同样的限制也适用于列名称。
图5-5 利用双引号来使用非标准名称
提示:
对象名称不能超过30个字符。字符可以是字母、数字、下划线、美元符号或者井字符号。
虽然像SQL*Plus和SQL Developer这样的工具会自动将小写字母转换为大写字母(除非名称包含在双引号内),但是请记住,对象名称总是区分大小写的。在下面这个示例中,两个表完全不同:
SQL> create table lower(c1 date); Table created. SQL> create table "lower"(col1 varchar2(2)); Table created. SQL> select table_name from dba_tables where lower(table_name) = 'lower'; TABLE_NAME ------------------------------ lower LOWER
注意:
尽管使用小写字母名称和非标准字符(甚至空格)是可以的,但这种做法并不好,因为可能引起混淆。
5.2.4 对象名称空间
一般而言,对象的唯一标识符是前缀为模式名的对象名称。但要全面理解对象的命名,还需要引入名称空间的概念。名称空间定义了一组对象类型,在这个组中,所有名称都必须由模式和名称唯一标识。不同名称空间中的对象可以共享相同的名称。
下面这些对象类型都共享相同的名称空间。
● 表 ● 独立的过程 ● 程序包 ● 用户定义类型和运算符
● 视图 ● 独立的存储函数 ● 物化视图
● 序列
● 私有同义词
因此不可能创建一个名称与表名相同的视图——至少,如果它们在相同的模式中,这是不可能的。一旦创建,SQL语句就会将视图当作表一样查找。表、视图和私有同义词共享相同的名称空间,这一点说明可以在用户看到的和实际的表之间建立几个抽象层,这对于安全性和简化应用程序开发来说都弥足珍贵。
下列对象类型都有自己的名称空间。
● 约束 ● 私有数据库链接
● 群集 ● 维度
● 数据库触发器
因此,即使是在同样的模式中,索引的名称也可能与表名相同(尽管不是个好主意)。
考点:
在同一个模式中,表、视图和同义词不能同名。
练习5-1 确定会话可以访问哪些对象
在这个练习中,将以用户HR身份来查询各种数据字典视图,确定HR模式中有哪些对象以及HR可以访问其他模式中的哪些对象。如果数据库中没有HR模式,请按照第7章中的指令创建它。
(1) 使用SQL*Plus或者SQL Developer,以用户HR身份连接到数据库。
(2) 确定HR模式中各种类型的对象数量:
select object_type, count(*) from user_objects group by object_type;
USER_OBJECTS视图将列出当前会话连接的模式(这里是HR)拥有的所有对象。
(3) 确定HR有权访问的对象的总数:
select object_type, count(*) from all_objects group by object_type;
ALL_OBJECTS视图将列出用户能够访问的所有对象。
(4) 确定谁拥有HR能够看见的对象:
select distinct owner from all_objects;
5.3 列举列可用的数据类型
当创建表时,每一列都分配一种数据类型,它决定了可以插入该列的值的特性。这些数据类型也用来指定PL/SQL过程和函数的参数的特性。选择数据类型时,必须考虑要保存的数据以及要在其上执行的操作。空间也是需要考虑的事项:有些数据类型是固定长度的,不管其中是什么数据,都占用相同的字节数;有些数据类型的长度则是可变的。如果没有填充列,那么Oracle根本不会给它提供任何空间。如果后面更新行来填充列,那么行会变得更大,而不管数据类型是固定长度还是可变长度。在12c数据库中,新的系统参数MAX_STRING_SIZE允许字符串数据类型从其默认值STANDARD改为EXTENDED时,比以前的版本大得多。
下面的数据类型适用于字母数字数据:
● VARCHAR2 可变长度的字符数据,如果MAX_STRING_SIZE=STANDARD,其长度就是从1B到4KB,如果MAX_STRING_SIZE=EXTENDED,其长度至多32 767字节。数据保存在数据库字符集中。
● NVARCHAR2 和VARCHAR2一样,但数据保存在国家语言字符集(它是许可的Unicode字符集之一)中。
● CHAR 固定长度的字符数据,从1B到2KB,它保存在数据库字符集中。如果数据的长度比列的长度短,就会用空格进行填充。
提示:
为了符合ISO/ANSI,可以指定VARCHAR数据类型,但这种类型的所有列都会自动转换为VARCHAR2。
下面的数据类型适用于二进制数据:
● RAW 变长的二进制数据,如果MAX_STRING_SIZE=STANDARD,则其长度为1~4000字节;如果MAX_STRING_SIZE=EXTENDED,则其长度可达32 767字节。与CHAR和VARCHAR2数据类型不同,在执行SELECT命令时,Oracle Net不会将RAW数据从数据库的字符集转换为用户进程的字符集,或者在执行INSERT命令时进行反向转换。
下面的数据类型适用于数字数据,它们都是可变长度的:
● NUMBER 数字数据,可以指定它的精度和小数位数。精度范围是1~38,小数位数范围是从-84~127。
● FLOAT 这是一个ANSI数据类型,精度为126位二进制、38位十进制的浮点数。Oracle还提供BINARY_FLOAT和BINARY_DOUBLE作为备选。
● INTEGER 相当于NUMBER,小数位数为零。
下面的数据类型适用于日期和时间数据,它们都是固定长度的:
● DATE 它的长度为零(如果列为空)或者7个字节。所有DATE数据都包含世纪、年、月、日、时、分和秒。其有效范围为公元前4712年1月1日至公元9999年12月31日。
● TIMESTAMP 如果列为空,那么它的长度为零,或者达到11字节(这取决于指定的精度)。与DATE类似,但对秒而言,其精度最多为9位,默认为6位。
● TIMESTAMP WITH TIMEZONE 和TIMESTAMP一样,但在保存数据时可以指定时区。根据精度,长度可能达到13个字节。该数据类型让Oracle通过将两个时间规范化为UTC来确定它们之间的差,即使这两个时间在不同的时区。
● TIMESTAMP WITH LOCAL TIMEZONE 和TIMESTAMP一样,但数据在保存时被规范化为数据库时区。当检索时,将其规范化为选择它的用户进程所在的时区。
● INTERVAL YEAR TO MONTH 用于记录两个DATE或者TIMESTAMP之间以年和月为单位的时间间隔。
● INTERVAL DAY TO SECOND 用于记录两个DATE或者TIMESTAMP之间以天和秒为单位的时间间隔。
下面是大对象数据类型:
● CLOB 保存在数据库字符集中的字符数据,大小没有限制:(4GB-1)×数据库块的大小。
● NCLOB 和CLOB一样,但数据保存在可选的国家语言字符集(它是许可的Unicode字符集之一)中。
● BLOB 和CLOB一样,但二进制数据不会被Oracle Net执行字符集转换。
● BFILE 定位器,它指向保存在数据库服务器的操作系统上的文件。文件的大小限制为264-1,但操作系统可以使用其他限制。
● LONG 数据库字符集中的字符数据,大小可达到2GB-1。LONG的所有功能(甚至更多)都由CLOB提供,不能在现代数据库中使用LONG,如果数据库有这种类型的列,应该将它们转换为CLOB。在表中只能有一个LONG列。
● LONG RAW 和LONG一样,但Oracle Net不会转换二进制数据。所有LONG RAW列都应该转换为BLOB。
下面是ROWID数据类型:
● ROWID 以64为基数编码的值,它是一个指向表中行的位置的指针。它加密了。它里面是物理地址。ROWID是Oracle专有的数据类型,除非特别选择,否则不可见。
考点:
所有考生都应该了解下面这些数据类型:VARCHAR2、CHAR、NUMBER、DATE、TIMESTAMP、INTERVAL、RAW、LONG、LONG RAW、CLOB、BLOB、BFILE和ROWID。还要详细了解VARCHAR2、NUMBER和DATE。
VARCHAR2数据类型必须用一个数来限定,这个数表示列的最大长度。如果插入列的值小于这个值,那么没有问题:这个值只占用必要的空间。如果这个值比最大值还长,那么INSERT会出现错误。如果将值更新为更长或者更短的值,那么列的长度(和行本身)也会相应改变。如果没有输入,或者更新为NULL,那么它根本不会占用空间。
可以使用精度和小数位数来限定NUMBER数据类型。精度设置数中的最大位数,最高位是最左端的非0数字,最低位是数中最右边的数字。小数位数是从小数点到最低位的位数。正的小数位数是小数点右边(包括它本身)到最低位的位数。负的小数位数是小数点左边(不包括它本身)到最低位的位数。
DATE数据类型总是包括世纪、年、月、日、时、分和秒——即使在插入时没有指定所有这些元素。必须指定年、月和日。如果省略时、分和秒,那么它们会默认为午夜。在日期上使用TRUNC函数,还可以把时、分和秒设置为午夜。
练习5-2 研究HR模式中的数据类型
在这个练习中,将通过两种方法找出在HR模式中表使用的数据类型:
(1) 使用SQL*Plus或者SQL Developer,以用户HR身份连接到数据库。
(2) 使用DESCRIBE命令显示某些表中的数据类型:
describe employees; describe departments;
(3) 像DESCRIBE命令那样,查询数据字典视图,显示组成EMPLOYEES表的列:
select column_name, data_type, nullable, data_length, data_precision, data_scale from user_tab_columns where table_name='EMPLOYEES';
视图USER_TAB_COLUMNS将显示当前用户模式中每个表的每一列的详细情况。