欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

达梦数据库中各种表的管理

程序员文章站 2022-03-03 22:25:13
...

上海蒙马软件技术有限公司

2021年7月28日

达梦数据库有:普通表、分区表、临时表、堆表(rowid)、列存表(HUGE)、外部表等 默认的普通表是索引组织部表(索引组织表,无主键利用 rowid,并发不好)。

普通表都是以 B 树形式存放的,ROWID 都是逻辑的 ROWID,即从 1 一直增长下去。在并发情况下,每次插入过程中都需要逻辑生成 ROWID,这样影响了插入数据的效率;对于每一条数据都需要存储 ROWID 值,也会花费较大的存储空间。堆表就是基于上述两个理由而提出的。

简单地说,堆表是指采用了物理 ROWID 形式的表,即使用文件号、页号和页内偏移而得到 ROWID 值,这样就不需要存储 ROWID 值,可以节省空间。逻辑 ROWID 在插入或修改过程中,为了确保 ROWID 的唯一性,需要依次累加而得到值,这样就影响了效率,而堆表只需根据自己的文件号、页号和页内偏移就可以得到 ROWID,提高了效率。

普通表都是以 B 树形式而存储在物理磁盘上,而堆表则采用一种“扁平 B 树”方式存储。

堆表的好处:并发插入的性能非常高,查询效率相对较低; 索引组织表:在插入的时候会自动建立索引,性能稍微低。

-- 通过一个参数可以查看默认创建的表是否为索引组织表、堆表。
-- LIST_TABLE 参数:默认情况下是0   0为索引组织表  1为堆表 
​
SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='LIST_TABLE';

一、普通表(索引组织表)

普通表都是以 B 树形式存放的,ROWID 都是逻辑的 ROWID,即从 1 一直增长下去。在并发情况下,每次插入过程中都需要逻辑生成 ROWID,这样影响了插入数据的效率;对于每一条数据都需要存储 ROWID 值,也会花费较大的存储空间。

创建普通表,id使用自增列。

CREATE TABLE comm_student (
id bigint identity,
name varchar(20),
birthday date,
math int,
english int,
science int
);
​
insert into comm_student 
select
dbms_random.string('1',trunc(dbms_random.value(3,8))),
current_date()-365*20+dbms_random.value(-365,365),
trunc(dbms_random.value(40,100)),
trunc(dbms_random.value(40,100)),
trunc(dbms_random.value(40,100))
from dual
connect by level <=100;
​
commit;
​
-- 或:
-- 通过存储过程添加随机生成数据
CREATE OR REPLACE PROCEDURE GEN_DATA(num int) AS
DECLARE
 id int;
BEGIN
 id:=1;
 while id <= num loop
  insert into comm_student values(
        dbms_random.string('1',trunc(dbms_random.value(3,8))),
        current_date()-365*20+dbms_random.value(-365,365),
        trunc(dbms_random.value(40,100)),
        trunc(dbms_random.value(40,100)),
        trunc(dbms_random.value(40,100)));
  id:=id+1;
 end loop;
END;
​
call GEN_DATA(100000);

反向生成DDL语句为:

CREATE TABLE "USER_MEMA"."student1"
(
"id" BIGINT IDENTITY(1, 1) NOT NULL,
"name" VARCHAR(20),
"birthday" DATE,
"math" INT,
"english" INT,
"science" INT) STORAGE(ON "TS_MEMA", CLUSTERBTR) ;

二、堆表

采用了物理 ROWID 形式的堆表,DM 服务器内部对聚集索引进行了调整,没有采用传统B 树结构,取而代之的是“扁平 B 树”,数据页都是通过链表形式存储。为支持并发插入,扁平 B 树可以支持最多 128 个数据页链表(最多 64 个并发分支和最多 64 个非并发分支),在 B 树的控制页中记录了所有链表的首、尾页地址。

对于非并发分支,如果分支数有多个,即存在多个链表,则不同的用户登录系统之后,会依据其事务 ID 号,随机选择一条链表来对堆表进行插入操作。

对于并发分支,则不同用户会选择不同的分支来进行插入,如果存在多个用户选择了同一条分支的情况,才需要等待其他用户插入结束并释放锁之后才能进行插入。在并发情况下,不同用户可以在不同的链表上进行插入,效率得到较大提升。

SQL 建表语句指定 创建表时可以在 STORAGE 选项中指定需要创建的表形式, 与堆表创建形式相关的关键字有三个,分别是 NO BRANCH、BRANCH、CLUSTERBTR。

  • NOBRANCH:如果指定为 NOBRANCH,则创建的表为堆表,并发分支个数为 0,非并发分支个数为 1;

  • BRANCH(n,m):如果为该形式,则创建的表为堆表,并发分支个数为 n,非并发个数为 m;

  • BRANCH n:指定创建的表为堆表,并发分支个数为 n,非并发分支个数为 0;

  • CLUSTERBTR:创建的表为索引组织表。

堆表由于其自身的特性,与普通表相比,也为自己增添了一些限制 1、没有聚集索引,如果用户需要借助聚集索引主键对数据进行排序则不推荐使用堆表; 2、DM 暂不支持堆表的列存储; 3、对表进行 alter 操作,数据记录 rowid 可能发生改变,会引起索引的重建。

CREATE TABLE heap_student (
id bigint identity,
name varchar(20),
birthday date,
math int,
english int,
science int
)
STORAGE ( BRANCH(4,2));
​
insert into heap_student 
select
dbms_random.string('1',trunc(dbms_random.value(3,8))),
current_date()-365*28+dbms_random.value(-366,366),
trunc(dbms_random.value(0,100)),
trunc(dbms_random.value(0,100)),
trunc(dbms_random.value(0,100))
from dual
connect by level <=10000;
​
commit;

堆表的维护 

 堆表在进行数据扫描过程中,有着其先天的优势。如果知道了数据记录的 ROWID,则直接可以对 ROWID 进行解码,得到该记录的文件号、页号和页内偏移,也就得到了该记录。   所以建议在经常查询的列上建立二级索引,这样在进行操作中,先通过二级索引找到记录ROWID,就可以直接找到数据,效率有较大提高。   堆表虽然支持表的 ALTER 操作,但是建议轻易不要进行此类操作。对表进行 ALTER操作,数据记录的 ROWID 有可能发生改变,这样每次进行 ALTER 操作,都可能进行索引的重建,需要花费较多的时间。   达梦数据库支持对堆表的备份与还原操作。还原数据时,B树数据和二级索引可以同时被还原。

三、HUGE表/列存储表

1、HUGE FILE SYSTEM:是大梦数据自有的,针对海量数据进行分析一种高效的表,列存储表是建立在HFS(分层文件管理系统)上的。 2、HUGE 表建立在自己特有的表空间上HUGE表空间,默认在HMAIN表空间上 。 3、相关信息存在V$huge_tablespace中。最多可以创建32767个huge表空间。 4、创建HUGE表时,根据with和without 来确定表是非事务还是事务型的HUGE表。 5、HUGE表与普通行表一样,可以进行增删改操作。 6、但HUGE表的删除与更新操作的效率会比行表低一些,并发操作性能会比行差一些。

HUGE表的一些限制: 1、支持定义 NULL , NOT NULL, UNIQUE ,PRIMARY KEY 2、 HUGE表不建立聚族索引,允许建立二级索引,不支持位图索引, 其中unique不检查唯一性。 3、不支持表空间限制 4、不支持大字段列 5、不支持全文索引 6、不支持建立触发器 7、不允许建触发器

达梦数据库初始化后,已经建立了一个HMAIN表空间,用来存放列存储表(HUGE Table)

CREATE HUGE TABLE huge_student (
id bigint,
name varchar(20),
birthday date,
math int,
english int,
science int
);
​
insert into huge_student 
select ROWNUM AS id,
dbms_random.string('1',trunc(dbms_random.value(3,8))),
current_date()-365*28+dbms_random.value(-366,366),
trunc(dbms_random.value(0,100)),
trunc(dbms_random.value(0,100)),
trunc(dbms_random.value(0,100))
from dual
connect by level <=1000000;
​
commit;

四、外部表

外部表是表的数据不会放在数据库里面,会放在操作系统的文件里面。通过数据库外部表可以查看外部文件的数据。 1、建立外部表时,不会产生页、簇、段等存储结构。 2、只能与表相关的定义放在数据库字典中,不能对外部表的内容进行修改(update 、instert、 delete) 3、不能对外部表创建索引。 4、外部表可以通过SQL语句解码器来完成。而不需要将外部表装载到数据库中。

用途:要访问其他数据并不在数据库当中,要查数据。

1、准备外部数据

创建一个文本文件data.txt

1,2,3,tom
4,5,6,jerry

2、配置控制文件data.ctl

LOAD DATA
INFILE '/opt/dm8/data/memadb/data.txt'
INTO TABLE TEST
FIELDS ','

3、创建外部表

CREATE EXTERNAL TABLE ext_tab(id int,c2 int,c3 int,name varchar(30))
FROM '/opt/dm8/data/memadb/data.ctl';

4、查询

SELECT * FROM ext_tab;

五、分区表

为提高数据库在大数据量读写操作和查询时的效率,达梦数据库提供了对表和索引进行分区的技术,把表和索引等数据库对象中的数据分割成小的单位,分别存放在一个个单独的段中,用户对表的访问转化为对较小段的访问,以改善大型应用系统的性能。 达梦提供了水平分区的方式,该方式包含了范围(range)、哈希(HASH)和列表(list)、间隔分区(interval)四种方法。

1、分区的概念

分区是指将表、索引等数据库对象划分为较小的可管理片段的技术,每一个片段称为分区子表或分区索引。 一个表被分区后,对表的查询操作可以局限于某个分区进行,而不是整个表,这样可以大大提高查询速度。 达梦采用子表方式创建分区表,分区表作为分区主表,而每一个分区以一个子表实体存在,即每一个分区都是一个完整的表,一般命名为主表名_分区名。 在创建表的语法中,使用partition子句指定分区方式和分区列,以及分区的名字等信息,即可创建分区表

2、分区的方法

(1) 范围(range)分区:对表中的某些列上值的范围进行分区,根据某个值的范围,决定将该数据存储在哪个分区上。 (2) 哈希(hash)分区:通过指定分区编号来均匀分布数据的一种分区类型,通过在I/O设备上进行散列分区,使得这些分区大小基本一致。 (3) 列表(list)分区:通过指定表中的某个列的离散值集,来确定应当存储在一起的数据。 (4)间隔(interval)分区:间隔分区其实和范围分区是一样的,但是它比范围分区要更加高级。范围分区需要我们手动的去分配每个范围区间,所以使用起来不是那么灵活。例如某公司的数据,想要以年度为分区范围,每年都要手动新增一个分区,比较麻烦。而间隔分区就能完美的解决此类问题。 (5) 多级分区表:上述三种方式的任意组合。

3、注意事项

1、解决分区表超出范围问题,范围分区关键字:MAXVALUE,列表分区DEFAULT。

2、局部唯一索引必须包含全部分区列,创建分区表如果表中有主键列,分区列必须包含主键。分区表中没有主键列或唯一索引列,则可以创建。

3、堆表即便有主键列或唯一索引列也可以创建分区。

4、水平分区堆表各子表必须位于同一个表空间。没有堆表的情况,分区表可以在不同表空间。

4、分区测试

准备工作

创建测试用户,添加一个随机生成城市名称的存储函数。

CREATE USER u_part IDENTIFIED BY Mema_1234 ;
--default table space ts_part;
GRANT resource TO u_part;
​
CONNECT u_part/Mema_1234
​
CREATE OR REPLACE FUNCTION GET_CITY() RETURN VARCHAR 
AS
    TYPE   cityArray IS VARRAY(10) OF VARCHAR(100);
    citys  cityArray;
BEGIN
   citys:=cityArray();
   citys.extend();
   citys(1):='上海';
   citys.extend();
   citys(2):='北京';
   citys.extend();
   citys(3):='广州';
   citys.extend();
   citys(4):='重庆';
   citys.extend();
   citys(5):='深圳';
   citys.extend();
   citys(6):='青岛';
   citys.extend();
   citys(7):='成都';
   citys.extend();
   citys(8):='香港';
   citys.extend();
   citys(9):='合肥';
   citys.extend();
   citys(10):='武汉';
   RETURN citys(trunc(dbms_random.VALUE(1,11)));
END;
/
​
select get_city();

1)范围分区

范围分区是按照某个列或几个列的值的范围来创建分区,当用户向表中写入数据时,数据库服务器将按照这些列上的值进行判断,将数据写入相应的分区中。在创建范围分区时,首先要指定分区列,即按照哪些列进行分区。 例如,创建一个表RANG_STUDENT,并进行分区:

CREATE TABLE RANG_STUDENT(
id bigint,
name varchar(20),
city varchar(10),
birthday date,
tel varchar(20),
email varchar(50),
math int,
english int,
science int
)
PARTITION BY RANGE (math)(
PARTITION FALED VALUES LESS THAN ('45'),
PARTITION BAD VALUES LESS THAN ('60'),
PARTITION GOOD VALUES LESS THAN ('80'),
PARTITION EXCELLENT VALUES EQU OR LESS THAN (MAXVALUE)
);

插入数据:

insert into RANG_STUDENT 
select
  level,
  dbms_random.string('1',trunc(dbms_random.value(3,8))),
  get_city(),
  current_date()-365*20+dbms_random.value(-365*3,365*3),
  to_char(10000000000+floor(dbms_random.value(3111111111,3999999999))),
  dbms_random.string('L',8)||'@'||dbms_random.string('L',5)||'.com',
  trunc(dbms_random.value(40,100)),
  trunc(dbms_random.value(40,100)),
  trunc(dbms_random.value(40,100))
  from dual
connect by level <=100000;

查询数据:

select * from RANG_STUDENT;
​
select * from RANG_STUDENT PARTITION(BAD);
select * from RANG_STUDENT PARTITION(FALED);
select * from RANG_STUDENT PARTITION(GOOD);
select * from RANG_STUDENT PARTITION(EXCELLENT);

查询字典信息:

select table_name , high_value, tablespace_name,partition_name from user_tab_partitions where  table_name='RANG_STUDENT';

注意:

分区表建议取消主键,建唯一性本地索引防止数据重复。如果表中一定要主键,则分区范围一定要包含主键列。

普通表存在自增列也无法分区。

范围分区支持 MAXVALUE 范围值的使用,MAXVALUE 相当于一个比任何值都大的值。

2)列表分区

建表:

CREATE TABLE LIST_STUDENT(
id bigint,
name varchar(20),
city varchar(10),
birthday date,
tel varchar(20),
email varchar(50),
math int,
english int,
science int
)
PARTITION BY LIST(city)(                         
PARTITION p1 VALUES ('北京', '天津'),                        
PARTITION p2 VALUES ('上海', '合肥'),                        
PARTITION p3 VALUES ('武汉', '长沙'),                        
PARTITION p4 VALUES ('广州', '深圳'),
PARTITION P0 VALUES (DEFAULT)                        
);

插入数据:

insert into LIST_STUDENT 
select
  level,
  dbms_random.string('1',trunc(dbms_random.value(3,8))),
  get_city(),
  current_date()-365*20+dbms_random.value(-365*3,365*3),
  to_char(10000000000+floor(dbms_random.value(3111111111,3999999999))),
  dbms_random.string('L',8)||'@'||dbms_random.string('L',5)||'.com',
  trunc(dbms_random.value(40,100)),
  trunc(dbms_random.value(40,100)),
  trunc(dbms_random.value(40,100))
  from dual
connect by level <=100000;

查询数据:

SELECT * FROM LIST_STUDENT;
SELECT * FROM LIST_STUDENT PARTITION(P0);
SELECT * FROM LIST_STUDENT PARTITION(P1);
SELECT * FROM LIST_STUDENT PARTITION(P2);
SELECT * FROM LIST_STUDENT PARTITION(P3);
SELECT * FROM LIST_STUDENT PARTITION(P4);

查询字典信息:

select table_name, high_value,tablespace_name,partition_name from user_tab_partitions
where TABLE_NAME='LIST_STUDENT';

3)哈希分区

建表:

CREATE TABLE HASH_STUDENT(
id bigint,
name varchar(20),
city varchar(10),
birthday date,
tel varchar(20),
email varchar(50),
math int,
english int,
science int
)
PARTITION BY HASH(name)(             
PARTITION p1,            
PARTITION p2,            
PARTITION p3,            
PARTITION p4            
); 

插入数据:

insert into HASH_STUDENT 
select
  level,
  dbms_random.string('1',trunc(dbms_random.value(3,8))),
  get_city(),
  current_date()-365*20+dbms_random.value(-365*3,365*3),
  to_char(10000000000+floor(dbms_random.value(3111111111,3999999999))),
  dbms_random.string('L',8)||'@'||dbms_random.string('L',5)||'.com',
  trunc(dbms_random.value(40,100)),
  trunc(dbms_random.value(40,100)),
  trunc(dbms_random.value(40,100))
  from dual
connect by level <=10000;

查询数据:

SELECT * FROM HASH_STUDENT;
​
SELECT * FROM HASH_STUDENT PARTITION(P1);
SELECT * FROM HASH_STUDENT PARTITION(P2);
SELECT * FROM HASH_STUDENT PARTITION(P3);
SELECT * FROM HASH_STUDENT PARTITION(P4);

查询数据字典:

select table_name, high_value, tablespace_name,partition_name from user_tab_partitions where  table_name='HASH_STUDENT';

4)间隔分区

间隔分区怎么用? 首先我们需要了解两个函数: NUMTOYMINTERVAL、NUMTODSINTERVAL 。 根据单词的组合,我们看到最后一个词是 INTERVAL (internal), 间隔,间隙的意思。 我们可以知道这是两个间隔函数。然后继续往前看, YM 、DS 这两个缩写,又是什么呢。 YM: YEAR MONTH 年、月。 DS: DAY SECOND 天、秒 很显然,这两个是表示时间间隔的间隔函数。

(1)NUMTOYMINTERVAL 间隔单位是年–>月(最小) (2)NUMTODSINTERVAL 间隔单位是天–>秒(最小)

建表:

CREATE TABLE INTE_STUDENT(
id bigint,
name varchar(20),
city varchar(10),
birthday date,
tel varchar(20),
email varchar(50),
math int,
english int,
science int
)
PARTITION BY RANGE (birthday)  INTERVAL(NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION "PART_1" VALUES LESS THAN (TO_DATE('1900-01-01 00:00:0','YYYY-MM-DD HH24:MI:SS'))
);

插入数据:

insert into INTE_STUDENT 
select
  level,
  dbms_random.string('1',trunc(dbms_random.value(3,8))),
  get_city(),
  current_date()-365*20+dbms_random.value(-365*3,365*3),
  to_char(10000000000+floor(dbms_random.value(3111111111,3999999999))),
  dbms_random.string('L',8)||'@'||dbms_random.string('L',5)||'.com',
  trunc(dbms_random.value(40,100)),
  trunc(dbms_random.value(40,100)),
  trunc(dbms_random.value(40,100))
  from dual
connect by level <=10000;

查询数据:

select * from inte_student;
select * from inte_student partition(SYS_P1386_1388)

查询数据字典:

select table_name, high_value, tablespace_name,partition_name from user_tab_partitions where  table_name='INTE_STUDENT';

5、普通表改为分区表

普通表改为分区表,要了解清楚被修改表的各种依赖关系,修改原表名称,按照原表字段结构创建新的分区表,导出原表数据做好备份,通过insert into <分区表> select * from <原表>的方式插入原数据。恢复各项约束和依赖。

创建普通分区:

CREATE TABLE comm_student (
id bigint identity,
name varchar(20),
city varchar(10),
birthday date,
tel varchar(20),
email varchar(50),
math int,
english int,
science int
);

插入记录:

insert into comm_student 
select
  dbms_random.string('1',trunc(dbms_random.value(3,8))),
  get_city(),
  current_date()-365*20+dbms_random.value(-365*3,365*3),
  to_char(10000000000+floor(dbms_random.value(3111111111,3999999999))),
  dbms_random.string('L',8)||'@'||dbms_random.string('L',5)||'.com',
  trunc(dbms_random.value(40,100)),
  trunc(dbms_random.value(40,100)),
  trunc(dbms_random.value(40,100))
  from dual
connect by level <=100000;

了解表的相关信息

-- 查看原表DDL
select dbms_metadata.get_ddl('TABLE','comm_student','u_part') from dual;
​
-- 检查原表的索引
select index_name,table_name,degree,status,partitioned from user_indexes t where table_name='comm_student';
​
-- 检查原表约束
select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE,INDEX_NAME,R_CONSTRAINT_NAME from dba_constraints where OWNER='u_part' and TABLE_NAME='comm_student';
​
-- 检查原表涉及的其他对象
select * from user_dependencies t where t.referenced_name = 'comm_student';
​
-- 检查基于EMP表创建的视图和触发器
-- 如果有
select dbms_metadata.get_ddl('VIEW','v_comm_student','u_part') from dual;
-- 如果有
select dbms_metadata.get_ddl('TRIGGER','TR_ROW_comm_student','u_part') from dual;
​
-- 检查原表的外键依赖
select t1.table_name, 
       t2.table_name as "TABLE_NAME(R)", 
       t1.constraint_name, 
       t1.r_constraint_name as "CONSTRAINT_NAME(R)",
       a1.column_name, 
       a2.column_name as "COLUMN_NAME(R)"
from user_constraints t1, user_constraints t2, user_cons_columns a1, user_cons_columns a2
where t1.table_name='comm_student' and
      t1.r_constraint_name = t2.constraint_name and 
      t1.constraint_name = a1.constraint_name and 
      t1.r_constraint_name = a2.constraint_name;
      
-- 查看表数据量
select segment_name,sum(bytes)/1024/1024 from dba_segments where segment_name='comm_student' and owner='u_part' group by segment_name;
​
-- 检查表空间使用情况,查看资源是否充足
select file_name,tablespace_name,bytes/1024/1024,maxbytes/1024/1024 from dba_data_files;

导出原表数据

dexp u_part/Mema_1234 directory=/opt/dm8/memadb/dmp file=comm_student.dmp log=comm_student.log tables=comm_student

重命名原表

alter table comm_student rename to comm_student_old;

创建分区表

CREATE TABLE P_COMM_STUDENT(
id bigint,
name varchar(20),
city varchar(10),
birthday date,
tel varchar(20),
email varchar(50),
math int,
english int,
science int
)
PARTITION BY RANGE (math)(
PARTITION FALED VALUES LESS THAN ('45'),
PARTITION BAD VALUES LESS THAN ('60'),
PARTITION GOOD VALUES LESS THAN ('80'),
PARTITION EXCELLENT VALUES EQU OR LESS THAN (MAXVALUE)
);

创建约束及唯一性本地索引,局部唯一索引必须包含全部分区列(略)

查看分区表信息(略)

插入原表数据

INSERT INTO p_comm_student SELECT * FROM comm_student_old;

重建依赖对象(略)

重建视图(略)

根据实际情况决定是否彻底drop掉emp_old表,释放空间。

六、临时表

1、在达梦里面不可以创建临时表空间,用户不能手动创建临时表空间; 2、可以创建临时表; 3、用户可以通过系统函数 sf_rest_temp_ts 释放表空间; 4、通过 select * from v$dm_ini where para_name link ‘%TEMP%’; 5、通过sp_set_para_value(2,‘temp_size’,200) 设置临时表空间大小; 6、临时表空间文件在磁盘占用大小不会缩减,用户可以通过sf_rest_temp_ts来进行磁盘空间清理; 7、TEMP表空间完全由达梦数据库自动维护。

-- 临时表分为两种级别:(事务级,会话级):
-- 1、on commit delete rows:临时表是事务级的,每次事务提交或回滚之后,表中的所有数据被删除。
-- 2、on commit paresrve rows:指定临时表是会话级,会话结束的时候清空表。
​
CREATE GLOBAL  TEMPORARY TABLE TEMP_SESSION_TAB (ID INT,NAME VARCHAR(20))
ON COMMIT PRESERVE ROWS; --创建基于会话级的临时表。
​
CREATE GLOBAL TEMPORARY TABLE TEMP_TRX_TAB (ID INT , NAME VARCHAR(20)) 
ON COMMIT DELETE ROWS;  --创建基于事务级临时表。
​
​
SELECT * FROM SYS.DBA_TABLES WHERE DBA_TABLES.TABLE_NAME  LIKE 'TEMP_%';

七、其他

1、随机数生成方式

-- 其他随机数生成方式
​
-- 随机生成某个范围的整数
select trunc(dbms_random.value(40,100));
​
-- 随机生成字符串
select dbms_random.string('1',trunc(dbms_random.value(3,8)));
​
-- 随机生成手机号
select to_char(10000000000+floor(dbms_random.value(3111111111,3999999999)));
​
-- 随机生成电子邮箱
select dbms_random.string('L',8)||'@'||dbms_random.string('L',5)||'.com';
​
-- 随机生成某段日期范围
select current_date()-365*20+dbms_random.value(-365,365),
​
-- 随机生成城市函数
CREATE OR REPLACE FUNCTION GET_CITY() RETURN VARCHAR AS
    TYPE   cityArray IS VARRAY(10) OF VARCHAR(100);
    citys cityArray;
BEGIN
   citys:=cityArray();
   citys.extend();
   citys(1):='上海';
   citys.extend();
   citys(2):='北京';
   citys.extend();
   citys(3):='广州';
   citys.extend();
   citys(4):='重庆';
   citys.extend();
   citys(5):='深圳';
   citys.extend();
   citys(6):='青岛';
   citys.extend();
   citys(7):='成都';
   citys.extend();
   citys(8):='香港';
   citys.extend();
   citys(9):='合肥';
   citys.extend();
   citys(10):='武汉';
   RETURN citys(trunc(dbms_random.VALUE(1,10)));
END;
/
​
select get_city();

2、批量删除模式下所有表

DECLARE
    VAR1     VARCHAR(20) := 'TEST';
    TAB_NAME VARCHAR(100);
    SQL1     VARCHAR(500);
    SQL2     VARCHAR(500);
    C1 CURSOR;
BEGIN
    SQL1 = 'SELECT TABLE_NAME FROM DBA_TABLES WHERE OWNER = '''||VAR1||''';';
    OPEN C1 FOR SQL1;
    LOOP
        FETCH C1 INTO TAB_NAME;
        EXIT WHEN C1%NOTFOUND;
        SQL2 = 'DROP TABLE "' || VAR1 || '"."' ||TAB_NAME || '";' ;
        EXECUTE IMMEDIATE SQL2;
    END LOOP;
    CLOSE C1;                   
END;
/