Oracle里面constraint说明

本文详细介绍了SQL中的约束(Constraint)概念,包括约束的目的、类型及其状态等。解释了Deferrable、Initially、Validate/NoValidate、Enable/Disable和Rely等约束状态的作用,并通过实例展示了这些状态如何影响数据的一致性和完整性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先来看一下《SQL Reference》中对于Constraint的说明:

 
    constraint-1.jpg
 
    下面说一下我的认识:
 
    1、Constraints的目的:
 
      设立Constraint就是为了让数据满足某些规则。

    2、Constraint的类型:
 
      not null    (不能为空)
      unique      (值必须唯一)
      primary key (not null + unique)
      goreign key (该表值必须在外键表中存在)
      check       (自己加的条件)
      ref         (不熟)

    注:Constraints不但可以建立在Table上,也可以建立在View上。

    3、Constraint的状态:
 
      ① Deferrable
      该参数用于指定是否可以是同set语句来进行临时控制constraint,时约束在commit时才生效
      DEFERRABLE:可以使用set constraint字句
      NOT DEFERRABLE:不可以使用set constraint字句(默认)
 
      ② Initially
      该参数用于建立默认的DEFERRABLE类型约束
      INITIALLY一般都要和IMMEDIATE、DEFERRED一起使用
      INITIALLY IMMEDIATE:在执行SQL时违反约束即报错(默认)
      INITIALLY DEFERRED:在提交时才报错
 
      ③ Validate | NoValidate
      该参数一般与Enabled和Disabled属性搭配使用
 
      ④ Enable
      该参数确认约束应用于数据
      ENABLE VALIDATE:将验证已经存在的和之后的操作是否符合约束(默认)
      ENABLE NOVALIDATE:不验证已经存在的数据,但对之后进行的操作有效
 
      ⑤ Disable
      该参数使约束失效
      DISABLE VALIDATE:约束失效标注,可用于暂时导入大量数据时,不进行索引更新
      DISABLE NOVALIDATE:约束失效,并不保证约束是否正确,即不保证已有数据满足约束(默认)
 
      ⑥ Rely
      Rely和Norely只能用在 ALTER TABLE MODIFY constraint 语句中
      Rely:告诉Oracle,不必对NOVALIDATE模式的约束的数据进行信任,即需要检验以前的数据
      (这个没用过,实在搞不准确切含义,还是把文档的内容直接放上来)
      constraint-2.jpg
 
    4、set语句
 
      constraint-3.jpg
 
 
 
 
----------------------------------------------------------------------------------------------------
转一篇Constraint的文章
----------------------------------------------------------------------------------------------------
 
 
constraints 三个需要注意的地方
 
1. deferrable
 
一个constraint如果被定义成deferrable那么这个constraints可以在deferred和imediate两种状态相互转换。deferred只在transaction中有效,也就是只可以在transaction过程中使constraint失效,但如果transaction commit的话,transaction会变成immediate。
 
SQL> create table cons_parent (id number(10),name varchar2(10));
Table created.
 
SQL> create table cons_child (id number(10),name varchar2(10));
Table created.
 
SQL> alter table cons_parent add primary key (id);
Table altered.
 
SQL>alter table cons_child add constraints chi_fk_par foreign key (id)
2   references cons_parent(id);
Table altered.
 
SQL> alter table cons_child add constraints chi_fk_par foreign key (id)
2 references cons_parent(id);
Table altered.
 
一个constraint默认是NOT DEFERRABLE的
 
SQL> select constraint_name||' '||deferrable from all_constraints
2    where constraint_name='CHI_FK_PAR';
 
CONSTRAINT_NAME||''||DEFERRABLE
---------------------------------------------
CHI_FK_PAR NOT DEFERRABLE
 
NOT DEFERRABLE的不能在deferred和imediate两种状态相互转换
 
SQL> set constraints chi_fk_par deferred;
SET constraints chi_fk_par deferred
*
ERROR at line 1:
ORA-02447: cannot defer a constraint that is not deferrable
 
SQL> alter table cons_child drop constraints chi_fk_par;
Table altered.
 
SQL> alter table cons_child add constraints chi_fk_par foreign key (id)
2    references cons_parent(id) deferrable;
Table altered.
 
SQL> select constraint_name||' '||deferrable from all_constraints
2    where constraint_name='CHI_FK_PAR';
 
CONSTRAINT_NAME||''||DEFERRABLE
---------------------------------------------
CHI_FK_PAR DEFERRABLE
 
一个constraint如果被定义成deferrable那么这个constraints可以在deferred和imediate两种状态相互转换
 
SQL> set constraints chi_fk_par immediate;
Constraint set.
 
SQL> insert into cons_child values (2,'llll')
insert into cons_child values (2,'llll')
*
ERROR at line 1:
ORA-02291: integrity constraint (SYSTEM.CHI_FK_PAR) violated - parent key not found
 
SQL> set constraints chi_fk_par deferred;
Constraint set.
 
SQL> insert into cons_child values (2,'llll');
1 row created.
 
SQL> set constraints chi_fk_par immediate;
SET constraints chi_fk_par immediate
*
ERROR at line 1:
ORA-02291: integrity constraint (SYSTEM.CHI_FK_PAR) violated - parent key not found
 
deferred只在transaction中有效,也就是只可以在transaction过程中使constraint失效,但如果transaction commit的话,transaction会变成immediate。
 
SQL> commit;
commit
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02291: integrity constraint (SYSTEM.CHI_FK_PAR) violated - parent key not found
deferrable会影响CBO的计划,并且正常情况下没有应用的必要,所以建议不要修改,而用系统默认的non deferrable
 


2. enable/disable validate/novalidate
 
enable/disable对未来的数据有约束/无约束。
 
validate/novalidate对已有的数据有约束/无约束。
 
如果加约束到一个大表,那么ORACLE会LOCK这个表,然后SCAN所有数据,来判断是否符合CONSTRAINT的要求,在繁忙的系统里显然是不合适的。所以用enable novalidate比较合适,因为ORACLE仅仅会LOCK表一小段时间来建立CONSTRAINT,当CONSTRAINT建立后再VALIDATE,这时检验数据是不会LOCK表的。
 
这方面很多书上都有例子,就不在这里累述了
 

3.REFERENCE 让人疑惑的地方
 
SQL>  create table wwm_father (id number,name varchar2(10),primary key (id,name))
Table created.
 
SQL> create table wwm_child (id number,name varchar2(10),
2    foreign key (id,name) references wwm_father on delete set null);
Table created.
 
SQL> insert into wwm_father values (6,'wwm');
1 row created.
 
SQL> insret into wwm_child values (6,'fff');
SP2-0734: unknown command beginning "insret int..." - rest of line ignored.
 
可以看出,REFERENCE是起作用的。但下面就有点让人疑惑了,似乎ORACLE不用该用这种策略来做,
 
SQL> insert into wwm_child values (6,null);
1 row created.
 
SQL> insert into wwm_child values(null,'lll');
1 row created.
 
SQL> insert into wwm_child values (null,null);
1 row created.
 
SQL> select * from wwm_father;
 
ID NAME
---------- --------------------
6 wwm
 
SQL> select * from wwm_child;
 
ID NAME
---------- --------------------
6
lll
 
SQL> select count(*) from wwm_child;
 
COUNT(*)
----------
3
 
可见,如果向CHILD表插入NULL的话,ORACLE默认认为NULL是匹配FATHER表里相关的REFERENCE的字段内容的。因此FOREIGN KEY的COLUMN大家就需要认真考虑是否要设置成NOT NULL了

<think>好的,我现在需要帮用户写一个Shell脚本,把Oracle的表结构转换成GBase 8a的。首先,我得理清楚Oracle和GBase 8a在数据类型和语法上的差异。用户可能不太熟悉这些差异,所以脚本需要处理这些转换点。 首先,用户可能需要从Oracle导出表结构。通常可以用DBMS_METADATA.GET_DDL来获取DDL语句,或者用SQL*Plus的DESCRIBE命令。不过导出DDL可能更方便,因为直接得到建表语句。假设用户已经导出了一个SQL文件,里面包含Oracle的建表语句。 接下来,数据类型转换是关键。比如,Oracle的VARCHAR2要转成GBase的VARCHAR,NUMBER转成DECIMAL或者根据精度调整。DATE类型可能不变,但要注意默认值。CLOB可能需要处理成TEXT,不过GBase 8a可能不支持,得确认。还有,Oracle的约束如主键、外键,GBase 8a的语法是否兼容?可能需要调整或者去掉,特别是如果GBase不支持某些约束的话。 然后,脚本需要逐行处理这个SQL文件。可以用sed或者awk来替换数据类型。比如用sed替换VARCHAR2为VARCHAR,替换NUMBER为DECIMAL。但要注意,NUMBER可能有参数,比如NUMBER(10,2),要保留参数。正则表达式需要精确匹配,避免误替换其他内容。 另外,Oracle的分区表语法可能和GBase不同,这部分可能需要更复杂的处理,或者暂时忽略,让用户手动调整。还有表注释和列注释,Oracle使用COMMENT ON,而GBase可能用不同的语法,需要转换。 权限部分,比如OracleTABLESPACE,在GBase中不需要,可能需要删除这些行。还有STORAGE参数等,GBase不支持的选项要去掉。 然后,需要考虑脚本的健壮性。比如,处理大小写问题,处理多个空格的情况,避免替换不准确。可能还需要处理引号的问题,Oracle可能使用双引号,而GBase是否支持,或者需要改成反引号? 最后,测试脚本,用几个Oracle的DDL例子跑一下,看看转换是否正确。比如,一个包含各种数据类型的表,是否有正确转换,约束是否正确处理。 总结步骤: 1. 导出Oracle的表结构为DDL文件。 2. 使用sed命令替换数据类型和关键字。 3. 处理约束和注释等语法差异。 4. 清理不支持的选项和语法。 5. 输出转换后的GBase 8a DDL文件。 可能遇到的问题:复杂的分区、索引、存储参数等需要手动处理。用户可能需要根据具体情况调整脚本,但基础的数据类型和简单结构可以自动转换。</think>以下是一个将Oracle表结构转换为GBase 8a表结构的Shell脚本示例,包含逐步说明: ```bash #!/bin/bash # 文件名:oracle2gbase8a_converter.sh # 用途:将Oracle DDL转换为GBase 8a兼容格式 # 输入文件参数检查 if [ $# -ne 1 ]; then echo "用法:$0 <oracle_ddl_file.sql>" exit 1 fi input_file=$1 output_file="converted_gbase8a_ddl.sql" # 主要转换操作 sed -E \ -e 's/VARCHAR2/VARCHAR/gi' \ -e 's/NUMBER\(\s*(\d+)\s*,\s*0\s*\)/DECIMAL(\1)/gi' \ -e 's/NUMBER\(\s*(\d+)\s*,\s*(\d+)\s*\)/DECIMAL(\1,\2)/gi' \ -e 's/NUMBER/DECIMAL/gi' \ -e 's/CLOB/TEXT/gi' \ -e 's/RAW\(\d+\)/VARBINARY/gi' \ -e 's/DATE/TIMESTAMP/gi' \ -e 's/ CONSTRAINT \w+//gi' \ -e 's/ ENABLE//gi' \ -e '/TABLESPACE/d' \ -e '/STORAGE/d' \ -e '/ PCTFREE/d' \ -e '/ INITRANS/d' \ -e '/ LOGGING/d' \ -e '/ COMPRESS/d' \ "$input_file" > "$output_file" echo "转换完成!输出文件:$output_file" ``` --- ### 关键转换逻辑说明: 1. **数据类型替换**: - `VARCHAR2` → `VARCHAR` - `NUMBER` → `DECIMAL`(自动处理精度转换) - `CLOB` → `TEXT` - `DATE` → `TIMESTAMP`(GBase 8a的DATE类型不支持时分秒) 2. **移除不兼容语法**: - 删除`TABLESPACE`、`STORAGE`等Oracle特有存储参数 - 移除`ENABLE`、`CONSTRAINT`等约束声明(GBase 8a对约束支持有限) 3. **特殊处理**: ```sql # 原始Oracle语句 CREATE TABLE employees ( emp_id NUMBER(6,0) PRIMARY KEY, name VARCHAR2(50), hire_date DATE ) TABLESPACE users; # 转换后GBase 8a语句 CREATE TABLE employees ( emp_id DECIMAL(6) PRIMARY KEY, name VARCHAR(50), hire_date TIMESTAMP ); ``` --- ### 使用步骤: 1. 从Oracle导出DDL: ```sql -- 使用SQL*Developer或执行以下SQL SELECT DBMS_METADATA.GET_DDL('TABLE', 'TABLE_NAME') FROM DUAL; ``` 2. 执行转换脚本: ```bash chmod +x oracle2gbase8a_converter.sh ./oracle2gbase8a_converter.sh oracle_ddl.sql ``` --- ### 需手动检查项: 1. **索引语法**: ```sql # Oracle CREATE INDEX idx_name ON table(col) TABLESPACE users; # GBase 8a CREATE INDEX idx_name ON table(col); ``` 2. **分区表**: GBase 8a使用`DISTRIBUTE BY`分布式语法,需重写Oracle的`PARTITION BY` 3. **函数转换**: `SYSDATE` → `CURRENT_TIMESTAMP` `TO_CHAR()` → `DATE_FORMAT()` --- 建议转换后使用GBase 8a的`gsql`工具验证语法: ```bash gsql -U username -d database -f $output_file ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值