引言
在数字化转型进程中,企业级应用对数据准确性和一致性的需求日益凸显。作为国产数据库的领军产品,KingbaseES凭借其高兼容性、强一致性、多语法支持和安全可控等核心优势,已成为金融、政务、电信等关键行业的不二之选。该产品采用创新的"一体化"架构设计,完美融合多应用场景需求,支持关系型、文档型、时序和GIS等多种数据模型,兼容Oracle/MySQL/PostgreSQL等多种语法体系,并具备分布式高可用集群能力,帮助开发者以更低的成本实现高性能SQL开发。
本文将从数据迁移中数据完整性和一致性的核心价值出发,深度解析KingbaseES的约束体系(包括NOT NULL、UNIQUE、PRIMARY KEY、FOREIGN KEY、CHECK等),揭示"数据库约束"的革命性效率优势。

一、数据完整性与一致性的价值体现
1.1 迁移过程中的完整性和一致性的致命缺陷
迁移过程中存在的完整性与一致性缺陷可能带来严重后果。这些关键性问题若未妥善解决,可能导致数据丢失、系统故障或业务中断,对整体迁移工作造成致命影响。确保数据完整性和系统一致性是迁移成功的基础条件,任何疏漏都可能引发连锁反应,威胁项目成败。
1.2 数据库约束的优势
数据库约束的优势包括:保证数据完整性(如主键约束防止重复记录),提高数据一致性(如外键约束维护表间关系),增强安全性(如非空约束避免空值错误),简化业务逻辑(如检查约束自动验证数据范围),提升查询效率(如索引约束加速检索)。这些约束在数据录入和修改时自动生效,减少人工校验成本。
二、KingbaseES约束体系介绍与实操案例
2.1 认识各种各样的索引
1、索引约束
创建唯一键或者主键约束后,KingbaseES数据库会自动创建索引。如果要使用包含外键约束的索引,需要手动创建。当已经存在约束索引时,再单独创建约束时数据库不会再自动为其创建索引。对于约束和索引的使用需要注意以下几点:
唯一约束和主键约束可以使用唯一索引;
约束和索引中的列顺序不需要一致;
如果已启用唯一或者主键约束,则不能删除对应的索引。需要先删除或者禁用该约束,才能删除索引。
2、主键约束
primary key主键约束列值唯一且非空。每张表只能有一个主键(主键可以是组合列,但是通常情况下,单列作为主键是最佳方案)。单列作为主键有以下特点:
唯一
非空
简短
提示
需要注意:在程序设计中尽量减少使用复合主键,组合列的值很长且不能用序列自动生成。
3、唯一约束
一般情况下,可以在不允许重复的非空列上使用unique唯一约束。例如,身份证号、员工编号等类型字段。
4、非空约束
数据库默认情况下,列可以包含null值。在以下情况下可以使用NOT NULL约束:
列必须为非空值;
允许数据库对表进行索引扫描。在索引列中必须要有一个非空列,数据库查询时才能使用索引扫描。
默认情况下,列的默认值为null。向表插入数据时,如果未指定列值,则插入默认值。可以在建表时使用default指定列的默认值,也可以之后再修改表定义指定默认值。在下面这些情况下可以指定默认值:
列包含非空约束;
列有一个最常见的值;
非空列在未指定值时,有一个默认值;
希望由数据库自动插入列值。
5、外键约束
当两张表共享一列或者多列数据时,可以使用foreign key外键约束来强制执行完整性约束,确保共享列在两张表中始终包含相同值。将一个表指定为引用表,另一个表为被引用表。被引用表中的共享列需要包含主键约束或唯一约束,引用表中的共享列。
引用外键约束。在外键列上定义额外的约束可能会影响引用关系。如果被引用键的主键约束或者唯一约束不存在或者被禁用,则无法启用外键。
6、管理外键约束
外键列的数据类型和名称
引用表和被引用表的共享列必须使用相同的数据类型,但列名可以不一样。
创建外键的权限
要创建外键,需要对引用表和被引用表都有访问权限。用户对被引用表的引用列有对象权限,对于引用表需要有建表权限。
外键的属性选择
KingbaseES数据库允许强制执行不同类型的外键约束。
默认设置下,数据库会阻止删除和更新被引用列操作;
设置外键为DELETE CASCADE 或 UPDATE CASCADE时,允许删除或者更新被引用键。这种情况下,引用键的数据行也会随之被删除或者更新;
设置外键为DELETE SET NULL 或 UPDATE SET NULL时,删除或者更新被引用键时,引用键的值会被置为空。
外键与空值
外键允许键值为空。如果要对复合外键中的空值增加完整性约束,可以再定义一个check约束。
引用表的关系
引用表和被引用表之间的关系可以通过被引用表外键列上的其他约束类型确定。
外键没有约束
当没有在外键上定义其他约束时,引用表中的列值可以引用相同的引用列值。并且允许外键为空值。
外键和非空约束
当外键不允许空值时,引用表中的每一行值都必须显式引用被引用表的键值,外键不存在空值。
外键和唯一约束
在外键上创建唯一约束后,引用表只存在一行可以引用被引用表的键值,外键允许存在空值。
外键和唯一非空约束
当外键上同时包含唯一约束和非空约束时,引用表只存在一行可以引用被引用表的键值,并且外键不允许为空值。
2.2 NOT NULL约束
NOT NULL约束确保指定列不接受NULL值,是数据完整性的基础保障。在KingbaseES中,NOT NULL可通过列定义或表约束实现:
sql
-- 列级定义
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL, -- 姓名必填
age INT
);
-- 表级定义(通过CHECK模拟)
CREATE TABLE products (
id INT,
price DECIMAL(10,2),
CHECK (price IS NOT NULL) -- 价格非空
);
场景对比:在订单系统中,订单金额必须为非空值。使用NOT NULL约束可确保所有插入操作自动验证,而应用程序只需处理业务逻辑,无需重复编写非空检查代码
2.3 UNIQUE约束
UNIQUE约束确保指定列或列组合的值唯一,是避免数据重复的核心手段。KingbaseES支持列级和表级UNIQUE约束:
sql
-- 列级唯一约束
CREATE TABLE users (
username VARCHAR(20) UNIQUE -- 用户名唯一
);
-- 表级唯一约束(多列组合)
CREATE TABLE invoices (
invoice_number VARCHAR(15),
fiscal_year INT,
UNIQUE (invoice_number, fiscal_year) -- 发票号+年度组合唯一
);
性能优化 :UNIQUE约束默认创建唯一索引,在大数据量场景下可通过部分索引优化
sql
CREATE UNIQUE INDEX idx_active_invoices
ON invoices (invoice_number, fiscal_year)
WHERE status = 'ACTIVE'; -- 仅对活跃发票建立唯一索引
2.4 PRIMARY KEY约束
PRIMARY KEY是NOT NULL与UNIQUE约束的组合,用于唯一标识表中的每行记录。KingbaseES支持单列主键与复合主键:
sql
-- 单列主键
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY, -- 客户ID主键
name VARCHAR(100)
);
-- 复合主键
CREATE TABLE order_items (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id) -- 订单项唯一标识
);
对比:在库存管理系统中,使用复合主键可确保同一订单的同一商品不会重复记录。相比应用程序层面的"订单ID+商品ID"组合验证,数据库主键直接保证唯一性,且性能更高。
2.5 FOREIGN KEY约束
FOREIGN KEY约束通过引用父表的主键或唯一键,确保子表数据与父表的一致性。KingbaseES支持丰富的引用选项:
sql
-- 创建父表
CREATE TABLE departments (
dept_id INT PRIMARY KEY,
dept_name VARCHAR(50)
);
-- 创建子表(带外键约束)
CREATE TABLE employees (
emp_id INT PRIMARY KEY,
dept_id INT REFERENCES departments(dept_id) ON DELETE CASCADE, -- 级联删除
name VARCHAR(50)
);
应用场景 :在人力资源系统中,员工部门引用支持级联更新 与限制删除
sql
ALTER TABLE employees
ADD CONSTRAINT fk_emp_dept
FOREIGN KEY (dept_id)
REFERENCES departments(dept_id)
ON UPDATE CASCADE -- 部门ID变更时自动更新员工记录
ON DELETE RESTRICT; -- 禁止删除存在关联员工的部门
2.6 CHECK约束
CHECK约束通过布尔表达式定义复杂的业务规则,是KingbaseES约束体系中最灵活的组件
sql
-- 列级CHECK约束
CREATE TABLE products (
price DECIMAL(10,2) CHECK (price > 0), -- 价格必须大于0
discount DECIMAL(10,2) CHECK (discount >= 0 AND discount <= 1) -- 折扣率0-1
);
-- 表级CHECK约束(多列逻辑)
CREATE TABLE orders (
order_total DECIMAL(10,2),
discount_total DECIMAL(10,2),
CHECK (order_total > discount_total) -- 订单总额必须大于折扣额
);
表达式扩展:CHECK约束支持复杂表达式,包括正则表达式、日期计算等
sql
-- 邮箱格式验证
ALTER TABLE users
ADD CONSTRAINT chk_email
CHECK (email ~* '^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$');
-- 出生日期范围验证
CREATE TABLE patients (
birth_date DATE,
CHECK (birth_date > '1900-01-01' AND birth_date < CURRENT_DATE)
);
三、约束管理的语法学习
3.1 约束的创建与修改
KingbaseES支持在创建表时定义约束,也支持通过ALTER TABLE动态添加或修改约束
sql
-- 添加约束
ALTER TABLE employees
ADD CONSTRAINT chk_salary
CHECK (salary >= 0); -- 工资非负
-- 修改约束定义
--启用约束
ALTER TABLE table_name
MODIFY CONSTRAINT public_table_name_constraint_1 ENABLE;
--设置约束为novalidate状态
ALTER TABLE table_name
MODIFY CONSTRAINT public_table_name_constraint_1 ENABLE novalidate;
3.2 约束重命名
和表对象一样,约束名必须是唯一的,不存在同名约束。创建约束时,如果未指定约束名,数据库会自动为约束命名。为了方便程序开发管理,建议最好是为约束统一命名,方便之后的约束管理。
使用alter语句来修改约束名,例如:
sql
ALTER TABLE table_name
RENAME CONSTRAINT public_table_name_constraint_1 to table_name_pk;
3.3 删除约束
通过ALTER TABLE DROP 语句来删除约束。要删除约束和依赖于它的所有其他完整性约束,可以指定cascade语句。例如:
sql
ALTER TABLE table_name DROP CONSTRAINT table_name_pk;
四、真实场景的索引使用
4.1 电商
电商应用场景中,通过约束机制确保订单数据的严格一致性
sql
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT NOT NULL REFERENCES customers(customer_id) ON DELETE RESTRICT,
order_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
total_amount DECIMAL(10,2) NOT NULL CHECK (total_amount > 0),
status VARCHAR(10) NOT NULL CHECK (status IN ('PENDING','SHIPPED','DELIVERED'))
);
CREATE TABLE order_items (
order_item_id SERIAL PRIMARY KEY,
order_id INT NOT NULL REFERENCES orders(order_id) ON DELETE CASCADE,
product_id INT NOT NULL REFERENCES products(product_id),
quantity INT NOT NULL CHECK (quantity > 0),
unit_price DECIMAL(10,2) NOT NULL CHECK (unit_price > 0)
);
订单高峰期采用异步约束检查机制提高系统吞吐量
sql
ALTER TABLE orders
SET CONSTRAINTS chk_total_amount DEFERRABLE; -- 将该约束设为可延迟模式
BEGIN TRANSACTION;
INSERT INTO orders (...) VALUES (...);
-- 执行相关业务处理逻辑
COMMIT; -- 事务提交时统一验证约束条件
4.2 金融
在金融业务场景中,数据约束机制能够确保交易信息的绝对准确性:
sql
CREATE TABLE accounts (
account_id VARCHAR(20) PRIMARY KEY,
customer_id INT NOT NULL REFERENCES customers(customer_id),
balance DECIMAL(15,2) NOT NULL CHECK (balance >= 0), -- 强制账户余额非负
currency CHAR(3) NOT NULL CHECK (currency IN ('USD','EUR','CNY')) -- 限定货币类型
);
CREATE TABLE transactions (
transaction_id SERIAL PRIMARY KEY,
from_account VARCHAR(20) NOT NULL REFERENCES accounts(account_id) ON DELETE RESTRICT,
to_account VARCHAR(20) NOT NULL REFERENCES accounts(account_id) ON DELETE RESTRICT,
amount DECIMAL(15,2) NOT NULL CHECK (amount > 0), -- 转账金额必须为正
transaction_time TIMESTAMP NOT NULL DEFAULT NOW(),
status VARCHAR(10) NOT NULL CHECK (status IN ('PENDING','COMPLETED','CANCELLED'))
);
数据一致性 :采用可串行化隔离级别 结合数据库约束来确保资金转账的原子性操作:
sql
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
UPDATE accounts SET balance = balance - 1000 WHERE account_id = 'ACC123';
UPDATE accounts SET balance = balance + 1000 WHERE account_id = 'ACC456';
COMMIT;
五、结语
KingbaseES凭借完善的约束机制,为数据迁移过程提供了可靠的数据完整性保障。相比应用层的数据校验,数据库约束在执行性能、开发效率和维护便捷性等方面展现出显著优势。通过熟练运用NOT NULL、UNIQUE、PRIMARY KEY、FOREIGN KEY和CHECK等约束,开发者能够构建出高效稳定、安全可靠的SQL代码,从而有效支撑业务的高质量发展。本文通过深度解析KingbaseES的约束体系,结合原创代码示例与生产场景,帮助开发者完成数据的迁移,为后续数据库的使用打下一定的基础,最终在数字化转型的浪潮中占据先机。