【赵渝强老师】达梦数据库的数据库对象

简介: 达梦数据库包含基本与复杂两大类数据库对象。基本对象如表、索引、视图、序列和同义词,通过单一DDL语句创建和管理。表是数据存储核心,支持多种数据类型;索引提升查询速度,常见类型包括聚集、唯一、函数等索引;视图提供虚表功能;序列生成有序整数;同义词简化对象访问。复杂对象包括存储过程、函数和触发器,需用DMSQL语言开发,适用于更复杂的业务逻辑处理。文中通过实例详细介绍了各类对象的创建与使用方法。

b300.png

达梦数据库中包含各种数据库对象,主要分为两大类型:基本数据库对象和复杂数据库对象。下面分别进行介绍。视频讲解如下:


一、 基本数据库对象

常见的基本数据库对象有:表、索引、视图、序列、同义词等。之所以叫做基本数据库对象是因为这些对象直接使用一条DDL(Data Definition Language,数据定义语言)语句即可创建和管理。


1.1  表


表是一种非常重要的数据库对象,DM数据库的数据都是存储在表中。DM数据库的表是一种二维结构,由行和列组成。表有列组成,列有列的数据类型。达梦数据库支持的数据类型主要有常规数据类型、位串数据类型、日期时间数据类型和多媒体数据类型。


这里值得说明的是,char(n)和varchar(n)中括号中n代表字符的个数,并不代表字节个数,比如char(30) 就可以存储30个字符。char和varchar 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。


下面通过一个例子来说明char和varchar在存储字符的时候的区别。

(1)创建表一张新的表

SQL> create table test1(v1 char(5),v2 varchar(5));


(2)往表中插入数据

SQL> insert into test1 values('abc  ','abc  ');


(3)查询表中的数据

SQL> select concat(v1,'*'),concat(v2,'*') from test1;
# 输出的结果如下:
行号     CONCAT(V1,'*') CONCAT(V2,'*')
---------- -------------- --------------
1          abc  *         abc*
# 从输出的结果可以看出,char同varchar 的区别在于前者长度不足时,
# 系统自动填充空格,而后者只占用实际的字节空间。另外,
# 实际插入表中的列长度要受到记录长度的约束,
# 每条记录总长度不能大于页面大小的一半。


1.2  索引

索引是与表相关的可选的结构(聚簇索引除外),它能使对应于表的SQL语句执行得更快,因为有索引比没有索引能更快地定位信息。DM8数据库的索引能提供访问表的数据的更快路径,可以不用重写任何查询而使用索引,其结果与不使用索引是一样的,但速度更快。DM数据库官方对索引的定义为:索引(Index)是帮助DM数据库高效获取数据的数据结构。DM数据库中默认索引类型是B+树索引。


达梦数据库提供了几种最常见类型的索引,对不同场景有不同的功能,它们是:

  • 聚集索引:每一个普通表有且只有一个聚集索引;
  • 唯一索引:索引数据根据索引键唯一;
  • 函数索引:包含函数/表达式的预先计算的值;
  • 位图索引:对低基数的列创建位图索引;
  • 位图连接索引:针对两个或者多个表连接的位图索引,主要用于数据仓库中;
  • 全文索引:在表的文本列上而建的索引。


# 提示:索引在逻辑上和物理上都与相关的表的数据无关,作为无关的结构,索引需要存储空间。 
# 创建或删除一个索引,不会影响基本的表、数据库应用或其他索引。
# 当插入、更改和删除相关的表的行时,达梦数据库会自动管理索引。
# 如果删除索引,所有的应用仍继续工作,但访问以前被索引了的数据时速度可能会变慢。


可以用create index语句明确地创建索引。下面通过一个简单的示例来演示如何创建普通的索引。

(1)在emp表的ename列上创建一个名为index_emp_ename的索引。

SQL> create index index_emp_ename on emp(ename);


(2)获取索引的ID号。

SQL> select name,id from sysobjects 
      where name='INDEX_EMP_ENAME' and subtype$='INDEX';
# 输出的信息如下:
行号        NAME              ID         
---------- --------------- -----------
1           INDEX_EMP_ENAME 33555654


(3)通过indexdef系统函数查看索引的定义。

SQL> select indexdef(33555654, 0);
# 输出的信息如下:
行号        INDEXDEF(33555654,0)                                                                  
---------- ----------------------------------------------
1             CREATE INDEX "INDEX_EMP_ENAME" 
                ON "EMP"("ENAME" ASC) STORAGE(ON "MAIN", CLUSTERBTR) ;
# 函数indexdef的定义如下:indexdef(index_id int, preflag int);
# 其中:
# index_id:索引id
# preflag:对象前缀个数。1表示导出模式名;0表示只导出对象名


(4)查询名叫KING的员工数据,并输出对应的SQL执行计划。

SQL> explain select * from emp where ename='KING';
# 输出的信息如下:
1   #NSET2: [1, 1, 172] 
2     #PRJT2: [1, 1, 172]; exp_num(9), is_atom(FALSE) 
3       #BLKUP2: [1, 1, 172]; INDEX_EMP_ENAME(EMP)
4         #SSEK2: [1, 1, 172]; scan_type(ASC), 
                                   INDEX_EMP_ENAME(EMP), 
                                   scan_range['KING','KING']
# 从输出的执行计划可以看出,该查询使用了索引index_emp_ename。


(5)使用系统函数sp_rebuild_index重建索引。

SQL> sp_rebuild_index('SCOTT', 33555660);
# 提示:当一个表经过大量的增删改操作后,表的数据在物理文件中可能存在大量碎片,从而影响访问速度。
# 另外,当删除表的大量数据后,若不再对表执行插入操作,索引所处的段可能占用了大量并不使用的簇,
# 从而浪费了存储空间。可以使用重建索引来对索引的数据进行重组,使数据更加紧凑,
# 并释放不需要的空间,从而提高访问效率和空间效率。
# DM8提供的重建索引的系统函数为:
# sp_rebuild_index(schema_name varchar(256), index_id int);
# 其中:
# scheam_name为索引所在的模式名
# index_id为索引id。
# 使用说明:
# 水平分区子表,临时表和系统表上建的索引不支持重建。
# 虚索引和聚集索引不支持重建。


1.3  视图


视图(VIEW)是一种虚表,其本身并不包含数据。它将作为一个select语句保存在数据字典中的。视图依赖的表叫做基表。通过视图可以展现基表的部分数据;视图数据来自定义视图的查询中使用的基表。在了解的视图的作用后,下面通过具体的步骤来演示如何使用视图。


(1)基于员工表emp创建视图。

SQL> create or replace view view1
as
select * from dmhr.employee where department_id=1001;
# 视图也可以基于多表进行创建,例如:
SQL> create or replace view view2
as
select employee.employee_name,employee.salary,department.department_name 
from dmhr.employee,dmhr.department
where employee.department_id=department.department_id;


(2)从视图中查询数据。

SQL> select employee_name,salary from view1;
# 输出的信息如下:
行号     EMPLOYEE_NAME SALARY     
---------- ------------- -----------
1          龚顺超     8000
2          陈伟婷     15853
3          何杭菊     15868
4          欧锋利     15878
5          薛辉明     15888
SQL> select * from view2 where rownum<=10;
行号     EMPLOYEE_NAME    SALARY      DEPARTMENT_NAME
------ ------------------ ----------- ---------------
1          马学铭        12345       总经理办
2          程擎武        9000        行政部
3          郑吉群        15000       开发部
4          陈仙       12000       市场部
5          金纬       10000       技术支持部
6          李慧军        10000       总经理办
7          常鹏程        5000        行政部
8          谢俊人        5000        市场部
9          苏国华        30000       总经理办
10         强洁芳        10000       行政部
10 rows got
# 这里使用了行号rownum只显示前10条记录。


(3)通过视图执行DML操作,例如:给1001号部门员工涨100块钱工资。

SQL> update view1 set salary=salary+100;
# 并不是所有的视图都可以执行DML操作。在视图定义时含义以下内容,视图则不能执行DML操作:
# (1)查询子句中包含distinct和组函数
# (2)查询语句中包含group by子句和order by子句
# (3)查询语句中包含union 、union all等集合运算符
# (4)where子句中包含相关子查询
# (5)from子句中包含多个表
# (6)如果视图中有计算列,则不能执行update操作
# (7)如果基表中有某个具有非空约束的列未出现在视图定义中,则不能做insert操作


(4)创建视图时使用WITH CHECK OPTION约束。

SQL> create or replace view view3
      as
      select * from dmhr.employee where salary <5000
      with check option;
# 提示:WITH CHECK OPTION表示对视图所做的DML操作,不能违反视图的WHERE条件的限制。


(5)在view3上执行update操作。

SQL> update view3 set salary=10000;
# 此时将出现下面的错误信息:
update view3 set salary=10000;
[-6603]:违反视图[VIEW3]CHECK约束.
已用时间: 4.332(毫秒). 执行号:0.


1.4  序列


序列(sequence)是DM数据库中的数据库实体之一。通过使用序列,多个用户可以产生和使用一组不重复的有序整数值。比如可以用序列来自动地生成主关键字值。序列通过提供唯一数值的顺序表来简化程序设计工作。例如,下面的语句将创建一个序列。


SQL> create sequence myseq;


一旦序列生成,用户就可以在SQL语句中用以下伪列来存取序列的值:

  • currval:返回当前的序列值;
  • nextval:如果为升序序列,序列值增加并返回增加后的值;如果为降序序列,序列值减少并返回减少后的值。


例如:

SQL> select myseq.nextval;
# 输出的信息如下:
行号     NEXTVAL             
---------- --------------------
1          1
SQL> select myseq.currval;  
# 输出的信息如下:
行号     CURRVAL             
---------- --------------------
1          1
# 提示:序列可以是循环的,当序列的值达到最大值/最小值时,序列将从最小值/最大值计数。
# 使用一个序列时,不保证将生成一串连续不断递增的值。例如,如果查询一个序列的下一个值
# 供insert使用,则该查询是能使用这个序列值的唯一会话。如果未能提交事务处理,
# 则序列值就不被插入表中,以后的insert将继续使用该序列随后的值。


1.5  同义词


同义词(Synonym)让用户能够为数据库的一个模式下的对象提供别名。同义词通过掩盖一个对象真实的名字和拥有者,并且对远程分布式的数据库对象给予了位置透明特性以此来提供了一定的安全性。同时使用同义词可以简化复杂的SQL语句。同义词可以替换模式下的表、视图、序列、函数、存储过程等对象。创建同义词的语法格式如下:

create [or replace] [public] synonym 
[<模式名>.]<同义词名> for [<模式名>.]<对象名>


例如,创建一个同义词代表员工表。

SQL> create synonym emp for dmhr.employee;


接下来就可以通过同义词查询员工数据了。

SQL> select count(*) from emp;
# 输出的信息如下:
行号        COUNT(*)            
---------- --------------------
1           858


关于同义词的使用需要注意以下两点:

  • 同义词分为全局同义词(public synonym)和非全局同义词。用户在自己的模式下创建同义词,必须有create synonym权限。用户要创建全局同义词(public synonym),必须有create public synonym权限;
  • 同义词创建时,并不会检查他所指代的同义词对象是否存在,用户使用该同义词时候,如果不存在指代对象或者对该指代对象不拥有权限,则会报错。


二、复杂数据库对象


达梦数据库提供的复杂数据库对象主要包括:存储过程、存储函数和触发器。之所以叫做复杂数据库对象,是因为这些对象需要使用DMSQL语言进行开发和管理。DMSQL程序是达梦数据库对标准SQL语言的扩展,是一种过程化SQL语言。在DMSQL程序中,包括一整套数据类型、条件结构、循环结构和异常处理结构等,DMSQL程序中可以执行SQL语句,SQL语句中也可以使用DMSQL函数。


2.1  存储过程和存储函数


存储过程(Stored Procedure)和存储函数(Stored Function)指存储在数据库中供所有用户调用的子程序,它们事先经过经编译后存储在数据库系统中。因此,调用存储过程和存储函数来完成业务逻辑,是可以提高性能的。存储过程和存储函数的结构类似,但是存储函数必须要有一个return子句用于返回函数的值;而存储过程没有return子句。尽管存储过程没有return子句,但却可以通过指定一个或者多个out参数来指定返回值。

创建存储过程的语法格式如下:

create [or replace] procedure 存储过程名称(参数列表)
as
  DMSQL子程序体;


创建存储函数的基本语法格式如下:

create [or replace] function 存储函数名称(参数列表)
return 函数返回值类型
as
  DMSQL子程序体;


2.1.1  【实战】创建和使用存储过程


下面通过具体的步骤来演示如何创建存储过程,以及如何在DM数据库中调用它。

(1)创建第一个存储过程sayhelloworld,输出Hello World字符串。

SQL> create or replace procedure dmhr.sayhelloworld
as
    --说明部分
begin
    dbms_output.put_line('Hello World');
end;
/


(2)存储过程创建成功后,可以在PL/SQL程序中调用它。例如下面的代码调用了两次存储过程dmhr.sayhelloworld()。

SQL> begin
     dmhr.sayhelloworld();
     dmhr.sayhelloworld();
end;
/
# 输出的信息如下:
Hello World
Hello World
DMSQL 过程已成功完成
已用时间: 0.909(毫秒). 执行号:3528.


(3)存储过程也可以是exec命令单独进行调用,例如:

SQL> exec dmhr.sayhelloworld;
# 输出的信息如下:
Hello World
DMSQL 过程已成功完成
已用时间: 0.455(毫秒). 执行号:3530.


2.1.2  【实战】创建和使用存储函数

存储函数与存储过程的最大区别就在于存储函数可以通过reture子句返回函数的值,而存储过程没有return子句。下面将通过一个具体的示例来演示如何使用存储函数,并且如何调用它。


(1)创建存储函数dmhr.queryEmpTotalIncome查询指定员工的年收入。

SQL> create or replace function dmhr.queryEmpTotalIncome(eno in number)
return number
as
   --定义引用型变量保存月薪和奖金
   psal dmhr.employee.salary%type;
   pcomm dmhr.employee.commission_pct%type;
begin
   -- 查询指定员工的薪水和奖金,并赋值给变量。
   select salary,commission_pct into psal,pcomm from dmhr.employee 
   where employee_id=eno;
  
   --返回年收入
   return psal*12+nvl(pcomm,0);
end;
/


(2)调用存储函数dmhr.queryEmpTotalIncome查询员工号是1001的年收入。

SQL> select dmhr.queryEmpTotalIncome(1001) "该员工的年收入";          
# 输出的信息如下:
行号        该员工的年收入
---------- ---------------------
1           361200


2.2  触发器

触发器是一种特殊的存储过程,它在创建后就存储在数据库中。触发器的特殊性在于它是建立在某个具体的表或视图之上的,或者是建立在各种事件前后的,而且是自动激发执行的,如果用户在这个表上执行了某个DML操作(insert、delete、update),触发器就被激发执行。

触发器常用于自动完成一些数据库的维护工作。例如,触发器可以具有以下功能:

  • 可以对表自动进行复杂的安全性、完整性检查;
  • 可以在对表进行DML操作之前或者之后进行其它处理;
  • 进行审计,可以对表上的操作进行跟踪;
  • 实现不同节点间数据库的同步更新。


DM数据库触发器分为两种不同的类型语句级触发器和元组级触发器,这两种不同类型的触发器在定义是通过for each row进行区分。

  • 语句级触发器

语句级触发器是指在指定的操作语句之前或者之后执行一次,不管这个操作影响了多少行记录。换句话说,语句级触发器针对是表。


  • 元组级触发器

元组级触发器是指触发语句作用的每一条记录都被触发。换句话说,行级级触发器就是针对是表中的每一行。在行级触发器中可以使用:old和:new关键字来表示同一行数据在操作之前和操作之后的值。以员工表(dmhr.employee)为例,:old.salary操作该行之前员工的薪水,而:new.salary表示操作该行之后员工的薪水。

# 提示:old和:new表示的表中同一行。区别是:old表示操作之前,
# 而:new表示操作之后。注意这里的冒号不能少。


下面是利用数据库的触发器可以实现安全性的检查。这里的需求是:禁止在非工作时间往员工表中插入数据。例如:今天如果是星期天就不允许在员工表上执行insert操作。


(1)创建语句级触发器dmhr.securityemp禁止在非工作时间往员工表中插入数据。

SQL> create or replace trigger dmhr.securityemp
before insert
on dmhr.employee
begin
 -- 判断当前时间是否是非工作时间
  if to_char(sysdate,'day') in ('星期六','星期日') or
     to_number(to_char(sysdate,'hh24')) not between 9 and 18 then
     --如果是在非工作时间,禁止insert操作抛出异常
     raise_application_error(-20001,'此时不允许插入员工数据');
  end if;
end;
/
# 触发器dmhr.securityemp中指定的非工作时间有两个:一个是周末;
# 另一个是早9点前和晚18点后。


(2)非工作时间在员工表上执行insert操作。

SQL> insert into dmhr.employee
(employee_id,employee_name,email,hire_date,job_id,salary,department_id) 
values(1234,'Tom','tom@126.com',sysdate,42,7000,706);
# 输出的信息如下:
[-20001]:此时不允许插入员工数据
-20001: SECURITYEMP line 9 .
已用时间: 2.673(毫秒). 执行号:0.


(3)删除触发器。

SQL> drop trigger dmhr.securityemp;



相关文章
|
3天前
|
SQL 数据库 Docker
【赵渝强老师】在Docker中运行达梦数据库
本文介绍了在Docker容器中部署达梦数据库(DM 8)的具体步骤,包括创建文件夹、下载安装包、导入镜像、启动容器、登录数据库及查看状态等操作。同时,通过视频讲解辅助理解。文中还分析了将数据库服务容器化的潜在问题,如数据安全性、硬件资源争用、网络带宽占用和额外隔离带来的挑战,指出数据库服务在生产环境中可能不适合容器化的原因。
【赵渝强老师】在Docker中运行达梦数据库
|
1天前
|
存储 SQL NoSQL
【赵渝强老师】达梦数据库的逻辑存储结构
本文介绍了达梦数据库的存储结构,包括逻辑和物理存储两部分。逻辑存储结构由数据库(Database)、表空间(Tablespaces)、段(Segments)、簇(Cluster)和页(Page)组成。数据库是最大逻辑单元,包含所有表、索引等;表空间由数据文件组成,用于存储对象;段由簇构成,簇包含连续的数据页;页是最小存储单元。文中还提供了查询表空间、段和页大小的SQL语句,并附有视频讲解和示意图。
|
6天前
|
SQL 存储 运维
【赵渝强老师】达梦数据库的客户端工具
本文介绍了达梦数据库的多种工具及其使用方法,包括disql交互式查询工具、数据库配置助手DBCA、DM管理工具、DM服务查看器、DM控制台工具、DM数据迁移工具、DM性能监视工具以及DM审计分析工具。每种工具的功能和操作步骤均有详细说明,并配有相关图片和代码示例,帮助用户更好地理解和使用这些工具,提升数据库管理和维护效率。
|
9天前
|
SQL 存储 数据库
【赵渝强老师】达梦数据库的归档模式
本文介绍了达梦数据库备份与恢复中重做日志文件的作用,重点讲解了归档模式的必要性及其配置方法。文章分析了非归档模式可能导致的数据丢失问题,并推荐使用归档模式以保障数据一致性和完整性。归档模式分为本地归档和远程归档:本地归档将重做日志存储在本地,而远程归档适用于集群环境,确保所有节点拥有完整日志。文中还详细展示了如何通过SQL命令开启归档模式,包括切换状态、设置路径及验证配置等步骤,并附有视频教程辅助理解。
|
1天前
|
存储 SQL 安全
【赵渝强老师】达梦数据库的物理存储结构
本文介绍了达梦数据库的存储结构及各类物理文件的作用。达梦数据库通过逻辑和物理存储结构管理数据,包含配置文件(如dm.ini、sqllog.ini)、控制文件(dm.ctl)、数据文件(*.dbf)、重做日志文件(*.log)、归档日志文件、备份文件(*.bak)等。配置文件用于功能设置,控制文件记录数据库初始信息,数据文件存储实际数据,重做日志用于故障恢复,归档日志增强数据安全性,备份文件保障数据完整性,跟踪与事件日志辅助问题分析。这些文件共同确保数据库高效、稳定运行。
|
4天前
|
存储 SQL 并行计算
【赵渝强老师】达梦数据库MPP集群的架构
达梦数据库提供大规模并行处理(MPP)架构,以低成本实现高性能并行计算,满足海量数据存储和复杂查询需求。DM MPP采用完全对等无共享体系,消除主节点瓶颈,通过多节点并行执行提升性能。其执行流程包括主EP生成计划、分发任务、各EP并行处理及结果汇总返回。为确保高可用性,建议结合数据守护部署。
|
6天前
|
关系型数据库 MySQL 数据库连接
docker拉取MySQL后数据库连接失败解决方案
通过以上方法,可以解决Docker中拉取MySQL镜像后数据库连接失败的常见问题。关键步骤包括确保容器正确启动、配置正确的环境变量、合理设置网络和权限,以及检查主机防火墙设置等。通过逐步排查,可以快速定位并解决连接问题,确保MySQL服务的正常使用。
114 82
|
1天前
|
关系型数据库 MySQL Java
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
|
2月前
|
关系型数据库 MySQL 数据库连接
数据库连接工具连接mysql提示:“Host ‘172.23.0.1‘ is not allowed to connect to this MySQL server“
docker-compose部署mysql8服务后,连接时提示不允许连接问题解决
|
9天前
|
消息中间件 缓存 NoSQL
缓存与数据库的一致性方案,Redis与Mysql一致性方案,大厂P8的终极方案(图解+秒懂+史上最全)
缓存与数据库的一致性方案,Redis与Mysql一致性方案,大厂P8的终极方案(图解+秒懂+史上最全)
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等