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

  • Post author:
  • Post category:其他

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

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;
/

版权声明:本文为weixin_44472170原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。