用户的模式(Schema)指的是用户账号拥有的对象集,在概念上可将其看作是包含表、视图、索引和权限定义的对象。在 DM 中,一个用户可以创建多个模式,一个模式中的对象(表、视图等)可以被多个用户使用。模式不是严格分离的,一个用户可以访问他所连接的数据库中有权限访问的任意模式中的对象。
系统为每一个用户自动建立了一个与用户名同名的模式作为其默认模式,用户还可以用模式定义语句建立其它模式。
采用模式的原因有几点:
- 允许多个用户使用一个数据库而不会干扰其它用户;
- 把数据库对象组织成逻辑组,让它们更便于管理;
- 第三方的应用可以放在不同的模式中,这样可以避免和其它对象的名字冲突。模式类似于操作系统层次的目录,只不过模式不能嵌套。
DM 模式可以通过 SQL 语句进行操作。DM 模式主要包含以下的模式对象:
- 表;
- 视图;
- 索引;
- 触发器;
- 存储过程/函数;
- 序列;
- 全文索引;
- 包;
- 同义词;
- 类;
- 外部链接。
在引用模式对象的时候,一般要在模式对象名前面加上模式名。具体格式如下:
[模式名].对象名
当然,在当前模式和要引用的模式对象所属的模式相同时,可以省略模式名。如果我们访问一个表时,没有指明该表属于哪一个模式,系统就会自动给我们在表前加上缺省的模式名。类似地,如果我们在创建对象时不指定该对象的模式,则该对象的模式为用户的缺省模式。
模式对象之外的其他对象统一称为非模式对象,非模式对象主要包括以下几种对象:
- 用户;
- 角色;
- 权限;
- 表空间。
13.1 在单个操作中创建多个模式对象
在 DM 数据库中,使用 CREATE SCHEMA 语句就可以创建一个空的模式对象,也可以在创建模式时,同时创建多个模式对象。CREATE SCHEMA 语句的语法说明参见《DM8_SQL 语言使用手册》。
下面的语句在创建模式 test 的同时,创建了属于模式 test 的一个序列和两张表。
CREATE SCHEMA TEST
CREATE SEQUENCE ADDRESS_SEQ INCREMENT BY 1
CREATE TABLE ADDRESS(
ADDRESSID INT,
ADDRESS1 VARCHAR(60) NOT NULL,
ADDRESS2 VARCHAR(60),
CITY VARCHAR(30) NOT NULL,
POSTALCODE VARCHAR(15) NOT NULL)
CREATE TABLE ADDRESS_TYPE(
ADDRESS_TYPEID INT PRIMARY KEY,
NAME VARCHAR(50) NOT NULL);
可以用下面的格式来引用 TEST 模式中的 ADDRESS 表:TEST.ADDRESS,如向 ADDRESS 表中插入一条数据。
INSERT INTO TEST.ADDRESS VALUES(1,'武汉市关山一路特 1 号光谷软件园 C6 栋 5 层','上海市闸北区江场三路 28 号 301 室','上海市','200436');
13.2 重命名模式对象
要重命名一个模式对象,那么这个模式对象必须在指定的模式里面。用户可以采用下面几种方式来重命名模式对象:
- 删除原有的模式对象,重新创建;
- 使用 ALTER … RENAME 语句(table)。
如果采用的是删除并重建模式对象的方式来重命名模式对象,那么所有的基于这个模式对象的授权都将失效。在模式对象重建之后,基于原对象的权限和角色必须重新授予。
如果使用的是 ALTER …RENAME 语句来重命名模式对象,那么所有基于原模式对象的权限将转移到重命名后的模式对象上,不需要重新授权。如重命名 TEST 上的 ADDRESS 表:
ALTER TABLE TEST.ADDRESS RENAME TO ADDRESS1;
如果一个用户 USER1 在 ADDRESS 上拥有查询、插入的权限,那么重命名之后,USER1 在 ADDRESS1 上同样拥有查询、插入权限。
在重命名一个模式对象之前,需要考虑以下影响:
- 所有基于重命名模式对象的视图和 DMSQL 语句块都将失效,在使用之前,必须重新编译;
- 所有基于重命名模式对象的同义词在使用的时候都会报错。
13.3 启用和停用触发器
触发器(TRIGGER)定义当某些与数据库有关的事件发生时,数据库应该采取的操作。触发器是在相关的事件发生时由服务器自动地隐式激发的。触发器是激发它们的语句的一个组成部分,即直到一个语句激发的所有触发器执行完成之后该语句才结束,而其中任何一个触发器执行的失败都将导致该语句的失败,触发器所做的任何工作都属于激发该触发器的语句。
一个触发器有两种不同的状态:
- 启用(ENABLED):处于开启状态的触发器在触发条件满足时,执行触发体。缺省状态下,新创建的触发器都处于开启状态;
- 禁止(DISABLED):处于禁止状态的触发器在触发条件满足时,也不会执行触发体。
要设置触发器的状态,可以通过 ALTER TRIGGER 语句来完成。用户必须满足以下条件:
- 拥有该触发器;
- 有 ALTER ANY TRIGGER 权限。
用户可以通过使用带有 ENABLED/DISABLED 选项的 ALTER TRIGGER 语句来启用/禁止触发器。
例 1 启用 addr_trig 触发器:
ALTER TRIGGER addr_trig ENABLE;
例 2 禁用 addr_trig 触发器:
ALTER TRIGGER addr_trig DISABLE;
13.4 管理完整性约束
完整性约束规则,限制表中一个或者多个列的值。约束子句可以出现在 CREATE TABLE 或者 ALTER TABLE 语句中,确定约束条件并指定受到约束的列。
13.4.1 完整性约束状态
用户可以指定一个约束是启用(ENABLE)或禁止(DISABLED)。如果启用一个约束,那么在插入数据或者是更新数据时会对数据进行检查,不符合约束的数据被阻止进入。如果约束是禁止(DISABLED)的,不符合约束的数据被允许进入数据库。
- 禁止约束
要执行完整性约束定义的规则,约束应当设置为开启状态。但是,在下面的情况下,从性能的角度考虑,可以暂时将完整性约束禁用。
- 导入大量的数据到一张表中;
- 做批处理操作并对一张表做大规模修改时;
- 导入导出一张表。
在上面三种情形下,暂时禁用完整性约束能提高系统的性能,特别是在数据仓库的情况下。在禁用约束的情况下,可以将违反约束规则的数据插入到表中,因此,用户应当在上面列表中的操作结束之后启用约束。
- 启用约束
在启用完整性约束的情况下,不满足约束规则的行是不能插入到表中的。
13.4.2 定义完整性约束
下面的 CREATE TABLE 和 ALTER TABLE 语句在定义的时候就启用完整性约束:
CREATE TABLE t_con (
id NUMBER(5) CONSTRAINT t_con_pk PRIMARY KEY);
ALTER TABLE t_con
ADD CONSTRAINT t_con_pk PRIMARY KEY (id);
使用 ALTER TABLE 语句来启用完整性约束,可能会失败,这是因为表中已存在的数据可能违反完整性约束条件。
当启用 UNIQUE 或者 PRIMARY KEY 约束时,系统就会创建一个对应的索引。
13.4.3 修改或删除现有的完整性约束
用户可以使用 ALTER TABLE 语句来启用、禁止、删除一个约束。当用户使用 UNIQUE 或者 PRIMARY KEY 约束时,系统会创建对应的索引;当这个约束被删除或者是被禁用,索引就会被删除。
- 禁用已被启用的约束
下面的 ALTER TABLE 语句可以禁止完整性约束:
ALTER TABLE t_con DISABLE CONSTRAINT t_con_pk;
当有外键引用 UNIQUE 或者 PRIMARY KEY 列时,用户不能禁用 UNIQUE 或者 PRIMARY KEY 约束。
- 删除约束
用户可以通过 ALTER TABLE 语句和 DROP CONSTRAINT 参数来删除完整性约束。如:
ALTER TABLE t_con DROP CONSTRAINT t_con_pk;
如果有外键引用约束(UNIQUE 或者 PRIMARY KEY)时,在删除约束时必须加上 CASCADE 参数,否则不能删除。
13.4.4 查看约束信息
用户可以在系统表 SYSOBJECTS 和 SYSCONS 中查询约束的信息。
例 在 sysobjects 系统表中查找约束名为 t_con_pk 的信息
SELECT * FROM SYSOBJECTS WHERE NAME='T_CON_PK';
查找所有约束的信息:
SELECT * FROM SYSOBJECTS WHERE TYPE$='CONS';
系统表 SYSOBJECTS 和 SYSCONS 的详细描述详见附录数据字典部分。
13.5 管理对象依赖性
在实际应用中,许多模式对象需要引用其他的对象。例如,一个视图中包含一个查询,其中引用了其他的表或视图。一个模式对象引用了别的对象被称为依赖对象,被引用的对象称为被依赖对象。
达梦数据库在对象被调用的时候自动重新编译,确保对象有效。
13.6 管理对象名称解析
DM 数据库对象名字是由两部分组成,之间用点号隔开。例如:TEST.ADDRESS。
对象分为两大类:一是 SQL 语句中的对象;二是 DMSQL 程序中的对象。两者解析方式不同。例如:SQL 语言中 A.B 的解析会优先解析为“模式.对象”,例如:模式 A 表 B。DMSQL 程序中 A.B 的解析会优先解析为“本模式下包.对象”,如本模式下的包 A.函数 B。
13.6.1 SQL 语句对象
- 如果只有一个名字,而没有点号。
在当前模式下寻找是否存在相同名字的对象,如果找到,则返回;否则报错。
- 如果有点号,首先检测对象名的第一部分,例如:在 TEST.SCHOOL.CLASS 中,TEST 就是第一部分。具体步骤下面详细介绍:
(1)寻找哪一个模式的名字和第一部分相同,如果找到,以此模式进行步骤 2);否则报错。
(2)在模式中需找是否有与对象名第二部分同名的对象,如果找到且待解析对象名只有两个部分,则返回;如果找到但待解析对象名多于两个部分,则转步骤 3);否则报错。例如 TEST.SCHOOL.CLASS,若 SCHOOL 表对象匹配成功,进入步骤 3);
(3)在上次匹配成功的对象中按层次依次查找待解析对象名的剩余部分,如果所有待解析对象名全部匹配成功,则返回;否则报错。例如 TEST.SCHOOL.CLASS,在 TEST 模式下中的 SCHOOL 表对象中寻找 CLASS 列对象,若找到,则返回。
13.6.2 DMSQL 程序对象
在 DMSQL 程序中,对象名字的解析规则如下:
- 如果只有一个名字,而没有点号。
在当前模式下寻找是否存在相同名字的对象,如果找到,则返回;否则报错。这一点与 SQL 语句对象一致。 - 如果有点号,首先检测对象名的第一部分,如在 TEST.ADDRESS 中,TEST 就是第一部分。具体步骤下面详细介绍:
1)寻找当前模式下是否存在包名与第一部分相同,如果找到,进行步骤 2),否则进行步骤 4)。
2)在步骤 1 的包中查找是否有与对象名第二部分同名的对象,若找到且待解析对象名只有两个部分,则返回。若找到但待解析的对象名多于两个,则进行步骤 3)。若包中不存在与第二部分同名的对象则报错。
3) 查找包含在前一个对象中并且和待解析对象名当前解析部分相同名字的对象,如果找到,循环步骤 3),直至所有的部分检测结束后再返回;如果没有找到,则直接报错。
4)查找是否存在模式名与对象名的第一部分相同,如果找到,以此模式进行步骤 5),否则以当前模式进行步骤 5)。
5)在模式中需找是否有与对象名第二部分同名的对象,如果找到且待解析对象名只有两个部分,则返回;如果找到但待解析对象名多于两个部分,则转步骤 6);否则报错。
6)在模式中查找包含在前一个对象中并且和待解析对象名当前解析部分相同名字的对象,如果找到,循环步骤 6),直至所有的部分检测结束后再返回;如果没有找到,则直接报错。如 TEST.SCHOOL.CLASS.STUDENT,在 TEST 模式下中的 SCHOOL 对象中寻找 CLASS 的对象,然后在 CLASS 对象中寻找 STUDENT 对象。
13.7 显示有关模式对象的信息
在 DM 数据库系统中,模式对象的信息主要记录在 SYSOBJECTS 系统表中。可以通过下面的语句来查询模式对象的相关信息。
SELECT * FROM SYSOBJECTS WHERE TYPE$ = 'SCHOBJ' OR TYPE$ = 'TABOBJ';
但是,SYSOBJECTS 系统表并不能将模式对象的所有信息存储起来。用户应该和其它系统表一起获得更加详细的信息。
如果用户想获得索引更详细的信息,可以查询 SYSINDEXES 表;如果用户想了解存储过程、函数等的定义信息,可以查询 SYSTEXTS 表;如果用户想了解更详细的约束的相关信息,可以查询 SYSCONS 表。(系统表的详细介绍参考附录 1。)