注册
达梦8,关于参数CTAB_SEL_WITH_CONS的验证
培训园地/ 文章详情 /

达梦8,关于参数CTAB_SEL_WITH_CONS的验证

阿白 2023/02/17 1462 0 0
看到管理员手册中说到这个参数,感觉比较有趣,就想来验证下,先摘录管理员手册原话如下:

++ 如 果 用 户 通 过 单 表 的 全 表 查 询 进 行 建 表 操 作 , 则 可 以 通 过 将 INI 参 数CTAB_SEL_WITH_CONS 置为 1 进行原始表上约束的拷贝,列上能拷贝的约束包括默认值属性、自增属性、非空属性以及加密属性,表上能拷贝的约束包括唯一约束、PK 约束以及 CHECK约束。也可将 CTAB_SEL_WITH_CONS 置为 2 进行原始表上表结构、分区信息、存储信息以及表约束的拷贝,其中表约束包括唯一约束、PK 约束以及 CHECK 约束。也可将CTAB_SEL_WITH_CONS 置为 3 同时进行 1 和 2 的拷贝。++
先查询一下这个参数的想信息:
SQL> select * from v$dm_ini where PARA_NAME like ‘CTAB_SEL_WITH_CONS’;

行号 PARA_NAME PARA_VALUE MIN_VALUE MAX_VALUE DEFAULT_VALUE MPP_CHK SESS_VALUE FILE_VALUE


       DESCRIPTION                                               PARA_TYPE

       --------------------------------------------------------- ---------

1 CTAB_SEL_WITH_CONS 0 0 2 0 N 0 0

       Whether to build constraints when creating table by query SYS

如上看到,这个参数最大只能支持到2,并不支持设置为3。希望管理员手册的作者在表述上可以更加严谨。实际上确实也不支持3(我在linux和windows两个平台都试了也不支持)。
SQL> alter system set ‘CTAB_SEL_WITH_CONS’=3;

alter system set ‘CTAB_SEL_WITH_CONS’=3;

已用时间: 10.964(毫秒). 执行号:0.

而后可以创建下具体实验环境:

建表语句如下:
SQL> CREATE TABLE STUDENT(
2 NAME VARCHAR(20),
3 AGE INT PRIMARY KEY,
4 SEX VARCHAR(10) CHECK (SEX IN (‘MAIL’,‘FEMAIL’)), GRADE INT CHECK (GRADE IN (7,8,9)))
5 PARTITION BY LIST(GRADE)
6 SUBPARTITION BY LIST(SEX) SUBPARTITION TEMPLATE
7 (
8 SUBPARTITION Q1 VALUES(‘MAIL’),
9 SUBPARTITION Q2 VALUES(‘FEMAIL’)
10 ),
11 SUBPARTITION BY RANGE(AGE) SUBPARTITION TEMPLATE
12 (
13 SUBPARTITION R1 VALUES LESS THAN (12),
14 SUBPARTITION R2 VALUES LESS THAN (15),
15 SUBPARTITION R3 VALUES LESS THAN (MAXVALUE)
16 )
17 (
18 PARTITION P1 VALUES (7),
19 PARTITION P2 VALUES (8),
20 PARTITION P3 VALUES (9)
21 );

警告: 列表分区未包含DEFAULT,可能无法定位到分区

操作已执行

已用时间: 50.302(毫秒). 执行号:602.

插入语句如下:

insert into student VALUES (‘a’,10,‘MAIL’,7);
insert into student VALUES (‘b’,11,‘MAIL’,8);
insert into student VALUES (‘c’,13,‘MAIL’,9);
insert into student VALUES (‘d’,16,‘MAIL’,7);

commit;

实际还创建了一个非全局索引。事后验证,这个索引确实不会被支持复制。支持复制的只有其表述中所说的约束和表结构。所以,如果使用这个语句进行一些类似于表容量收缩等操作,请千万谨慎。因为可能漏掉其相关的索引或外键等。

先设置此参数为2
SQL> alter system set ‘CTAB_SEL_WITH_CONS’=2;
DMSQL 过程已成功完成
已用时间: 12.958(毫秒). 执行号:625.
SQL> create table student_new as select * from student;
操作已执行
已用时间: 137.429(毫秒). 执行号:626.

SQL> select tabledef(‘SYSDBA’,‘STUDENT_NEW’);

警告: 字符串截断

行号 TABLEDEF(‘SYSDBA’,‘STUDENT_NEW’)


1 CREATE TABLE “SYSDBA”.“STUDENT_NEW”
(
“NAME” VARCHAR(20),
“AGE” INT NOT NULL,
“SEX” VARCHAR(10),
“GRADE” INT,
NOT CLUSTER PRIMARY KEY(“AGE”),
CHECK(SEX IN (‘MAIL’, ‘FEMAIL’)) --约束
,CHECK(GRADE IN (7, 8, 9)))
PARTITION BY LIST(“GRADE”)
SUBPARTITION BY LIST(“SEX”) SUBPARTITION TEMPLATE
(
SUBPARTITION “Q1” VALUES(‘MAIL’) STORAGE(ON “MAIN”),
SUBPARTITION “Q2” VALUES(‘FEMAIL’) STORAGE(ON “MAIN”)
),
SUBPARTITION BY RANGE(“AGE”) SUBPARTITION TEMPLATE
(
SUBPARTITION “R1” VALUES LESS THAN(12) STORAGE(ON “MAIN”),
SUBPARTITION “R2” VALUES LESS THAN(15) STORAGE(ON “MAIN”),
SUBPARTITION “R3” VALUES LESS THAN(MAXVALUE) STORAGE(ON “MAIN”)
)
(
PARTITION “P1” VALUES(7) STORAGE(ON “MAIN”, CLUSTERBTR) ,
PARTITION “P2” VALUES(8) STORAGE(ON “MAIN”, CLUSTERBTR) ,
PARTITION
已用时间: 2.323(毫秒). 执行号:627.

再将此参数设置为1:
SQL> alter system set ‘CTAB_SEL_WITH_CONS’=1;
DMSQL 过程已成功完成
已用时间: 9.582(毫秒). 执行号:646.
SQL> create table student1 as select * from student;
操作已执行
已用时间: 9.791(毫秒). 执行号:647.

仅复制了约束,并未复制表结构:
SQL> select tabledef(‘SYSDBA’,‘STUDENT1’);

行号 TABLEDEF(‘SYSDBA’,‘STUDENT1’)


1 CREATE TABLE “SYSDBA”.“STUDENT1”
(
“NAME” VARCHAR(20),
“AGE” INT NOT NULL,
“SEX” VARCHAR(10),
“GRADE” INT,
NOT CLUSTER PRIMARY KEY(“AGE”),
CHECK(SEX IN (‘MAIL’, ‘FEMAIL’))
,CHECK(GRADE IN (7, 8, 9))) STORAGE(ON “MAIN”, CLUSTERBTR) ;
已用时间: 0.751(毫秒). 执行号:648.
SQL>

验证完全后,这里提一下触发器吧。因为删除表,触发器也会一起级联被删除。所以专门想尝试一下。我仅仅对表重命名,然后看表的触发器是否可用就好了。触发器创建及有效性如下:

SQL> CREATE OR REPLACE TRIGGER STUDENT_TRIGGER
2 BEFORE INSERT
3 ON STUDENT
4 FOR EACH ROW --表示行级触发器
5
6 BEGIN
7 if :new.AGE<7 then
8 RAISE_APPLICATION_ERROR(-20001,‘未到达入学年龄’);
9 END if;
10 end;
11 /

操作已执行
已用时间: 9.427(毫秒). 执行号:606.
SQL> insert into student VALUES (‘e’,6,‘MAIL’,7); --可以看到触发器已生效
insert into student VALUES (‘e’,6,‘MAIL’,7);
[-20001]:未到达入学年龄
-20001: STUDENT_TRIGGER line 8 .
已用时间: 1.497(毫秒). 执行号:0.

修改表名尝试如下:

SQL> ALTER TABLE STUDENT RENAME TO STUDENT_BAK;
操作已执行
已用时间: 29.489(毫秒). 执行号:628.
SQL> alter table student_new rename to student;
操作已执行
已用时间: 26.868(毫秒). 执行号:629.

触发器还是否生效呢?

失效了,实际这个触发器还是存在的,但是就是不再有效。主要是因为触发器跟随原表的表名变化而变化了。

图片.png

重新编译下试试。

SQL> CREATE OR REPLACE TRIGGER STUDENT_TRIGGER
2 BEFORE INSERT
3 ON STUDENT
4 FOR EACH ROW --表示行级触发器
5
6 BEGIN
7 if :new.AGE<7 then
8 RAISE_APPLICATION_ERROR(-20001,‘未到达入学年龄’);
9 END if;
10 end;
11 /

CREATE OR REPLACE TRIGGER STUDENT_TRIGGER
BEFORE INSERT
ON STUDENT
FOR EACH ROW --表示行级触发器
BEGIN
if :new.AGE<7 then
RAISE_APPLICATION_ERROR(-20001,‘未到达入学年龄’);
END if;
end;
第10 行附近出现错误[-3007]:替换触发器[STUDENT_TRIGGER]属性不一致.
已用时间: 0.245(毫秒). 执行号:0.
SQL> insert into student VALUES (‘e’,6,‘MAIL’,7);
影响行数 1
已用时间: 0.257(毫秒). 执行号:649.
SQL> rollback;
操作已执行
已用时间: 0.310(毫秒). 执行号:650.
SQL>

无法进行编译。只能删除此触发器重建了。实际仔细观察,会发现这里触发器已经被修改对象为STUDENT_BAK表了。这个坑在迁移时一定要注意。
评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服