维护数据完整性(一)

数据完整性约束

以下是关于 Oracle 数据完整性约束的表格:

约束类型描述示例语法(创建表时)示例语法(修改表时)
实体完整性约束 - 主键约束(PRIMARY KEY)表中一列或一组列值唯一标识每行记录,不允许重复和空值CREATE TABLE employees (employee_id NUMBER(10) PRIMARY KEY, employee_name VARCHAR2(50));ALTER TABLE employees ADD CONSTRAINT pk_employees PRIMARY KEY (employee_id);
实体完整性约束 - 唯一约束(UNIQUE)确保列或列组值唯一,允许空值(表可多个唯一约束)CREATE TABLE employees (employee_email VARCHAR2(100) UNIQUE);ALTER TABLE employees ADD CONSTRAINT uk_employees_email UNIQUE (employee_email);
域完整性约束 - 非空约束(NOT NULL)指定列不允许空值CREATE TABLE employees (employee_name VARCHAR2(50) NOT NULL);ALTER TABLE employees MODIFY employee_name VARCHAR2(50) NOT NULL;
域完整性约束 - 检查约束(CHECK)定义列取值范围或条件CREATE TABLE orders (order_quantity NUMBER CHECK (order_quantity > 0));ALTER TABLE orders ADD CONSTRAINT ck_order_quantity CHECK (order_quantity > 0);
参照完整性约束 - 外键约束(FOREIGN KEY)建立两表关联,外键引用另一表主键或唯一约束列CREATE TABLE orders (order_id NUMBER, employee_id NUMBER, CONSTRAINT fk_orders_employees FOREIGN KEY (employee_id) REFERENCES employees(employee_id));ALTER TABLE orders ADD CONSTRAINT fk_orders_employees FOREIGN KEY (employee_id) REFERENCES employees(employee_id);
操作描述示例语法
查看约束信息通过数据字典视图查看约束,USER_CONSTRAINTS 查当前用户表约束,DBA_CONSTRAINTS 查所有表约束(需权限)SELECT constraint_name, constraint_type, table_name FROM USER_CONSTRAINTS WHERE table_name = ‘EMPLOYEES’;
禁用约束暂时禁用约束,如数据导入时提高性能ALTER TABLE employees DISABLE CONSTRAINT pk_employees;
启用约束恢复约束作用,数据需符合条件ALTER TABLE employees ENABLE CONSTRAINT pk_employees;

完整性约束例子


-- 创建departments表
CREATE TABLE departments (
    department_id INT PRIMARY KEY,
    department_name VARCHAR(255) NOT NULL
);

-- 创建employees表
CREATE TABLE employees (
    employee_id INT PRIMARY KEY,
    first_name VARCHAR(255) NOT NULL,
    last_name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    department_id INT,
    salary DECIMAL(10, 2) CHECK (salary > 0),
    hire_date DATE NOT NULL,
    -- 外键约束,确保department_id存在于departments表中
    FOREIGN KEY (department_id) REFERENCES departments(department_id)
);

-- 添加一个唯一性约束,确保不会有相同的姓名组合
ALTER TABLE employees
ADD CONSTRAINT uc_employee_name UNIQUE (first_name, last_name);

-- 添加一个检查约束,确保email字段包含'@'符号
ALTER TABLE employees
ADD CONSTRAINT chk_email_format CHECK (email LIKE '%@%');


# employee_id是主键,确保每条记录都有一个唯一的标识符。
# email字段有一个唯一性约束,确保不会有重复的电子邮件地址。
# department_id是外键,它引用departments表中的department_id,确保员工只能分配到存在的部门。
# salary字段有一个检查约束,确保工资必须大于0。
# first_name和last_name字段都有非空约束,确保这些字段在插入记录时不能为空。
# 通过ALTER TABLE语句添加了一个唯一性约束uc_employee_name,确保first_name和# last_name的组合是唯一的。
# 通过ALTER TABLE语句添加了一个检查约束chk_email_format,确保电子邮件地址符合基本格式(包含’@'符号)。

CHECK约束的特点和使用规则

CHECK约束是一种用于限制列中值的条件,确保插入或更新的数据满足特定的逻辑条件。以下是描述的详细解释:

  • 可以在列级别或表级别定义
    • 列级别:CHECK约束可以直接在列定义时指定,只针对该列的值进行检查。
    • 表级别:CHECK约束也可以在表定义之后,使用单独的语句添加,可以涉及多个列的值。
  • CHECK子句中指定的条件应评估为布尔结果
    • CHECK约束的条件必须是一个表达式,其结果为布尔值(TRUE或FALSE)。如果条件为TRUE,则允许插入或更新操作;如果为FALSE,则操作将被拒绝。
  • 条件可以引用同一行中的其他列的值
    • 在CHECK约束的条件表达式中,可以引用同一行中的其他列的值来进行比较或计算。
  • 条件不能使用查询
    • CHECK约束的条件不能包含子查询,即不能使用SELECT语句来获取条件值。
  • 不能使用环境函数和伪列
    • 在CHECK约束的条件中,不能使用如SYSDATE(当前日期和时间)、USER(当前用户名)、USERENV(返回当前会话的环境信息)、UID(用户标识符)等环境函数,以及如ROWNUM(行号)、CURRVAL(序列当前值)、NEXTVAL(序列下一个值)或LEVEL(层次查询中的级别)等伪列。
  • 一个列可以有多个CHECK约束
    • 一个列可以定义多个CHECK约束,每个约束都可以检查不同的条件。
  • 列可以具有NULL值
    • 即使列上有CHECK约束,该列仍然可以接受NULL值,除非CHECK约束明确禁止了NULL值。
      总的来说,这段描述是在说明CHECK约束的语法规则和使用限制,以及它在数据库中的作用。

演示例子

CREATE TABLE tt(
    id int CONSTRAINT my_ct1 NOT NULL,
    name char(10) NOT NULL,
    sex char(1) NOT NULL,
    age int
);
ALTER TABLE tt ADD CONSTRAINT age_ct CHECK(age >= 0);
INSERT INTO tt VALUES(0, 'boobooke', 'M', 10);
-- 下面的插入语句会因为违反CHECK约束而失败
-- INSERT INTO tt VALUES(0, 'boobooke', 'M', -10);
commit;
SELECT * FROM tt;
-- 在添加新的CHECK约束之前,应该先删除旧的约束
-- ALTER TABLE tt DROP CONSTRAINT age_ct;
-- 然后添加新的约束
-- ALTER TABLE tt ADD CONSTRAINT age_ct CHECK(age > id);

在执行最后一个ALTER TABLE语句之前,需要先删除原有的age_ct约束,否则会因为约束名重复而失败。

唯一性约束(Unique Constraints)

  • 列级别的唯一性约束:
  • 对于单个列的唯一键(即该列的每个值都必须是唯一的),可以在列级别定义唯一性约束。
  • 表级别的唯一性约束:
  • 对于多列唯一键(也称为复合键),唯一性约束应该在表级别定义。在Oracle中,一个复合唯一键最多可以包含32个列。
  • 唯一性索引的创建:
  • Oracle会在唯一键列上创建一个唯一性索引来强制执行唯一性。如果表中已经存在具有相同列的唯一索引或非唯一索引,Oracle将使用现有索引。
  • 使用现有索引:
  • 如果要使用现有的非唯一索引来强制唯一性约束,表不能包含任何重复的键值。
  • 唯一性约束允许NULL值:
  • 唯一性约束允许在约束列中存在NULL值。这意味着,尽管列中的每个非NULL值必须是唯一的,但可以有多个NULL值,因为NULL值在数据库中被视为不确定的,不等于任何其他NULL值。
    以下是这些描述的示例SQL语句:
-- 创建表并定义单个列的唯一性约束
CREATE TABLE employees (
    employee_id INT CONSTRAINT emp_id_unique UNIQUE,
    first_name VARCHAR2(50) NOT NULL,
    last_name VARCHAR2(50) NOT NULL
);
-- 创建表并定义多列的唯一性约束
CREATE TABLE employees (
    employee_id INT NOT NULL,
    first_name VARCHAR2(50) NOT NULL,
    last_name VARCHAR2(50) NOT NULL,
    CONSTRAINT emp_name_unique UNIQUE (first_name, last_name)
);
-- 使用现有的非唯一索引作为唯一性约束
-- 假设有一个现有的非唯一索引 idx_emp_email
-- 首先确保没有重复的键值,然后添加唯一性约束
ALTER TABLE employees ADD CONSTRAINT emp_email_unique UNIQUE (email) USING INDEX idx_emp_email;

在最后一条语句中,USING INDEX子句指定了要使用的现有索引。这要求该索引覆盖了唯一性约束中指定的所有列,并且表中不存在违反唯一性的重复键值。

ALTER TABLE BONUS ADD CONSTRAINT UQ_EMP_ID UNIQUE (DEPT, EMP_ID)
USING INDEX TABLESPACE INDX STORAGE (INITIAL 32K NEXT 32K PCTINCREASE 0);
ALTER TABLE EMP ADD SSN VARCHAR2 (11) CONSTRAINT UQ_SSN UNIQUE;

可以为创建键时隐式创建的索引指定存储。如果没有指定存储,索引将在默认表空间的默认存储参数上创建。您可以像创建索引时那样指定LOGGING和NOSORT子句。创建的索引可以是本地分区索引或全局分区索引。索引将与唯一约束同名。
以下是两个示例。第一个示例定义了一个包含两列的唯一约束,并为索引指定了存储参数。第二个示例向EMP表添加了一个新列,并在列级别创建了唯一键。

-- 修改BONUS表,添加一个名为UQ_EMP_ID的唯一约束,该约束作用于DEPT和EMP_ID两列
-- 使用INDX表空间,并为索引指定存储参数:初始大小为32K,后续大小为32K,不增加百分比
ALTER TABLE BONUS ADD CONSTRAINT UQ_EMP_ID UNIQUE (DEPT, EMP_ID)
USING INDEX TABLESPACE INDX STORAGE (INITIAL 32K NEXT 32K PCTINCREASE 0);
-- 修改EMP表,添加一个名为SSN的列,数据类型为VARCHAR2(11)
-- 并在该列上创建一个名为UQ_SSN的唯一约束
ALTER TABLE EMP ADD SSN VARCHAR2 (11) CONSTRAINT UQ_SSN UNIQUE;

详细解释和介绍相关知识:

  • 存储参数:在Oracle中,可以为索引指定存储参数,这些参数定义了索引的物理存储特性。INITIAL参数指定了初始分配给索引的存储空间大小,NEXT参数指定了当初始空间被填满后,为索引分配的额外空间的块大小,PCTINCREASE参数指定了每次分配额外空间时增加的百分比。
  • LOGGING和NOSORT子句:LOGGING子句指定在创建索引时,操作将被记录到数据库的重做日志中,这是默认行为。NOSORT子句指定在创建索引时,不需要对数据进行排序,这通常适用于数据已经按照索引列的顺序排列的情况。
  • 分区索引:Oracle支持分区索引,这允许将索引数据分布在多个物理段上,可以是本地分区索引(与表分区相同的方式分区)或全局分区索引(可以与表分区不同方式分区)。
  • 索引名称:在Oracle中,当创建唯一约束时,如果没有明确指定索引名称,则默认情况下,索引的名称将与唯一约束的名称相同。
    在第一个示例中,USING INDEX子句用于指定索引的存储参数,包括表空间和存储参数。在第二个示例中,ADD子句用于向现有表添加新列,并通过CONSTRAINT子句在同一语句中为新列创建唯一约束。
CREATE TABLE t(id int, name char(10));
ALTER TABLE t ADD CONSTRAINT unique_id UNIQUE(id);
SELECT object_name, object_type FROM user_objects;
DROP INDEX unique_id;  # 无法删除该索引

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

远歌已逝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值