金仓数据库基础语法实操全解析(含可直接运行案例,避坑指南)

0 阅读11分钟

 前言

作为一名长期深耕国产数据库领域的技术博主,最近收到很多粉丝私信,询问金仓数据库的基础语法操作——毕竟随着国产化替代的推进,金仓数据库在政务、金融、能源等关键领域的应用越来越广泛,掌握其基础语法,已经成为不少开发者的必备技能。

不同于一些开源数据库,金仓数据库是一款拥有完全自主知识产权的企业级通用数据库,具备高可靠、高性能、高安全的特性,其语法设计遵循SQL标准,同时针对企业级场景做了诸多优化,上手难度不算高,但有很多细节需要注意,稍不留意就会踩坑。

本文将从实操角度出发,全面解析金仓数据库的基础语法,涵盖数据库与模式管理、表操作、数据操纵、查询语句、函数与存储过程等核心模块,嵌入3处可直接复制运行的代码案例,每一个语法点都结合实际应用场景说明,同时标注常见错误和避坑技巧,确保大家看完就能上手,避免出现“语法能看懂,运行跑不通”的问题。

一、金仓数据库基础认知(必看,避坑前提)

1.1 核心定位与特性

金仓数据库(KingbaseES,简称KES)是电科金仓自主研发的企业级大型通用数据库,成立于1999年,是国内成立最早的拥有自主知识产权的国产数据库企业,也是中国电子科技集团成员企业。截至目前,金仓数据库已在多家国有大型银行、省级政务云平台、重点能源集团及轨道交通运营单位完成规模化部署,累计装机部署超过100万套,连续多年在国产数据库关键应用领域销售套数占比第一。

核心特性总结(贴合开发者实操场景):

  • 语法兼容:遵循SQL标准,同时兼容Oracle、MySQL等主流数据库语法,开发者无需重新学习,可快速上手;
  • 自主可控:核心源代码自主率达到100%,通过多项国家权威认证,满足重点行业合规要求;
  • 高可用性:支持主备复制、读写分离集群等多种部署形态,配合故障检测与自动切换机制,可实现秒级服务恢复;
  • 实操友好:提供完善的命令行工具和图形化管理工具,语法逻辑清晰,报错信息直观,便于问题排查。

1.2 实操环境准备

本文所有语法实操均基于以下环境,大家可参考搭建,避免因环境差异导致代码运行失败:

  • 操作系统:CentOS 7.9(x86_64),Windows 10/11(图形化工具操作);
  • 金仓数据库版本:KingbaseES V9 2025(最新稳定版);
  • 连接工具:kingbase客户端(命令行)、Kingbase Studio(图形化工具);
  • 权限说明:所有操作均使用拥有管理员权限的账号(如system),避免因权限不足导致操作失败。

注意:金仓数据库并非开源产品,请勿尝试寻找所谓“开源版本”,如需使用,可通过官方渠道获取合法授权和安装包,具体可参考金仓官网相关指引。

1.3 基础语法通用规则(避坑重点)

在开始学习具体语法前,先明确几个通用规则,这些规则是避免语法错误的关键,也是很多新手容易踩坑的地方:

  1. 大小写敏感:金仓数据库对标识符(数据库名、表名、列名)的大小写敏感,建议统一使用小写,避免因大小写不一致导致查询失败;关键字(如CREATE、SELECT、INSERT)不区分大小写,但建议统一大写,提升代码可读性;
  2. 语句结束符:所有SQL语句必须以分号(;)结束,否则数据库会认为语句未完成,无法执行;
  3. 注释规则:单行注释使用“-- ”(两个减号+空格),多行注释使用“/* 注释内容 */”,注释内容不会被执行,建议在复杂语句中添加注释,便于后续维护;
  4. 数据类型匹配:插入、更新数据时,必须保证数据类型与表结构中定义的类型一致,否则会报类型不匹配错误;
  5. 权限控制:创建、删除、修改数据库对象(表、视图等)时,需确保当前账号拥有对应权限,否则会报权限不足错误。

二、数据库与模式管理语法(基础操作,必掌握)

数据库是金仓数据库的最高级逻辑容器,模式(Schema)则是数据库下的子逻辑容器,用于组织表、视图等对象,避免同名对象冲突。这部分语法是所有操作的基础,必须熟练掌握。

2.1 数据库操作(创建、查询、修改、删除)

2.1.1 创建数据库

语法格式(严谨版,包含常用参数):

CREATE DATABASE 数据库名
[ WITH 
  [ OWNER = 用户名 ]          -- 指定数据库所有者
  [ ENCODING = '编码格式' ]   -- 指定数据库编码,常用UTF8
  [ LC_COLLATE = '排序规则' ] -- 排序规则,常用zh_CN.UTF8
  [ LC_CTYPE = '字符分类' ]   -- 字符分类,常用zh_CN.UTF8
  [ TABLESPACE = 表空间名 ]   -- 指定表空间,默认使用默认表空间
  [ CONNECTION LIMIT = 连接数限制 ] -- 最大连接数,0表示无限制
];

实操说明:

  • 编码格式推荐使用UTF8,避免中文乱码问题;
  • 创建数据库的账号必须拥有CREATE DATABASE权限,管理员账号(system)默认拥有该权限;
  • 数据库名不能包含特殊字符(如@、#、$),建议使用字母、数字、下划线组合,且长度不超过63个字符。

示例(可直接运行):

CREATE DATABASE 数据库名
[ WITH 
  [ OWNER = 用户名 ]          -- 指定数据库所有者
  [ ENCODING = '编码格式' ]   -- 指定数据库编码,常用UTF8
  [ LC_COLLATE = '排序规则' ] -- 排序规则,常用zh_CN.UTF8
  [ LC_CTYPE = '字符分类' ]   -- 字符分类,常用zh_CN.UTF8
  [ TABLESPACE = 表空间名 ]   -- 指定表空间,默认使用默认表空间
  [ CONNECTION LIMIT = 连接数限制 ] -- 最大连接数,0表示无限制
];

运行结果:执行成功后,可通过查询语句查看数据库列表,确认数据库创建成功。

2.1.2 查询数据库

常用查询语句(3种方式,按需使用):

-- 方式1:查询所有数据库(最常用)
SELECT datname FROM sys_database;

-- 方式2:查询当前连接的数据库
SELECT current_database();

-- 方式3:查询数据库详细信息(包含所有者、编码、连接数等)
SELECT datname, datowner, encoding, datconnlimit 
FROM sys_database 
ORDER BY datname;

实操说明:sys_database是金仓数据库的系统表,存储所有数据库的基本信息,普通用户只能查看自身有权限的数据库。

2.1.3 修改数据库

语法格式(常用修改项):

ALTER DATABASE 数据库名
[ RENAME TO 新数据库名 ]          -- 修改数据库名
[ OWNER TO 新用户名 ]            -- 修改数据库所有者
[ CONNECTION LIMIT = 新连接数 ]  -- 修改最大连接数
[ SET TABLESPACE = 新表空间名 ]; -- 修改数据库默认表空间

注意:修改数据库名时,需确保该数据库没有被任何用户连接,否则会修改失败;修改所有者时,新所有者必须拥有CREATE DATABASE权限。

示例(可直接运行):

-- 将test_db的数据库名修改为demo_db,最大连接数修改为150
ALTER DATABASE test_db
RENAME TO demo_db;

ALTER DATABASE demo_db
SET CONNECTION LIMIT = 150;

2.1.4 删除数据库

语法格式:

DROP DATABASE [ IF EXISTS ] 数据库名;

实操说明:

  • IF EXISTS:可选参数,避免因数据库不存在而报错;
  • 删除数据库前,必须断开所有与该数据库的连接,否则删除失败;
  • 删除数据库是不可逆操作,删除后数据会彻底丢失,务必谨慎操作,建议删除前做好备份。

示例(可直接运行):

-- 删除demo_db数据库(先确保无连接)
DROP DATABASE IF EXISTS demo_db;

2.2 模式操作(创建、查询、修改、删除)

模式相当于数据库下的“文件夹”,用于分类管理表、视图等对象,避免不同业务的对象混淆。默认情况下,金仓数据库会创建一个public模式,所有未指定模式的对象都会默认存储在public模式下。

2.2.1 创建模式

语法格式:

CREATE SCHEMA [ IF NOT EXISTS ] 模式名
[ AUTHORIZATION 用户名 ]; -- 指定模式所有者,默认是当前创建者

实操说明:创建模式的账号必须拥有CREATE SCHEMA权限,管理员账号默认拥有该权限;模式名建议与业务模块对应(如user_schema、order_schema),便于管理。

示例(可直接运行):

-- 创建名为user_schema的模式,所有者为system
CREATE SCHEMA IF NOT EXISTS user_schema
AUTHORIZATION system;

-- 创建名为order_schema的模式,使用默认所有者(当前登录账号)
CREATE SCHEMA IF NOT EXISTS order_schema;

2.2.2 查询模式

常用查询语句:

-- 方式1:查询当前数据库下所有模式
SELECT nspname FROM sys_namespace;

-- 方式2:查询当前用户有权限的模式
SELECT nspname FROM sys_namespace
WHERE nspowner = (SELECT usesysid FROM sys_user WHERE usename = current_user);

-- 方式3:查看当前模式搜索路径(优先搜索的模式)
SHOW search_path;

实操说明:模式搜索路径(search_path)决定了数据库查询对象时的搜索顺序,默认值为“$user,public”,即先搜索与当前用户名同名的模式,再搜索public模式。

2.2.3 修改模式

语法格式(常用修改项):

ALTER SCHEMA 模式名
[ RENAME TO 新模式名 ]          -- 修改模式名
[ OWNER TO 新用户名 ];          -- 修改模式所有者

注意:修改模式名时,需确保该模式下没有正在被使用的对象(如正在查询的表),否则会修改失败。

示例(可直接运行):

-- 将user_schema改名为user_center_schema
ALTER SCHEMA user_schema RENAME TO user_center_schema;

-- 将order_schema的所有者修改为test_user(需先创建test_user账号)
CREATE USER test_user WITH PASSWORD 'Test@123456';
ALTER SCHEMA order_schema OWNER TO test_user;

2.2.4 删除模式

语法格式:

-- 方式1:删除空模式(模式下无任何对象)
DROP SCHEMA [ IF EXISTS ] 模式名;

-- 方式2:删除模式及模式下所有对象(强制删除)
DROP SCHEMA [ IF EXISTS ] 模式名 CASCADE;

实操说明:

  • CASCADE:可选参数,用于强制删除模式及模式下的所有对象(表、视图、函数等),慎用;
  • 如果模式下有对象,未使用CASCADE参数会删除失败;
  • 删除模式前,建议先查看模式下的对象,确认无需保留后再操作。

示例(可直接运行):

-- 强制删除user_center_schema模式及所有对象
DROP SCHEMA IF EXISTS user_center_schema CASCADE;

-- 删除空的order_schema模式
DROP SCHEMA IF EXISTS order_schema;

2.3 模式切换与使用技巧

在实际开发中,我们经常需要切换模式,操作表等对象,常用方法有3种:

  1. 指定模式+对象名(最常用,无需切换模式):

    -- 访问user_center_schema模式下的user表
    SELECT * FROM user_center_schema.user;
    
  2. 切换当前模式(临时生效,仅当前会话有效):

    -- 切换到user_center_schema模式
    SET search_path TO user_center_schema;
    -- 此时可直接访问该模式下的对象,无需指定模式名
    SELECT * FROM user;
    
  3. 修改当前用户的默认模式(永久生效):

    ​​​​​​​ -- 将当前用户的默认模式修改为user_center_schema
    ALTER USER current_user SET search_path TO user_center_schema;
    

避坑点:如果不指定模式,数据库会按照search_path的顺序搜索对象,若存在同名对象,会优先返回搜索到的第一个对象,容易导致查询错误,建议在多模式场景下,明确指定模式名。

三、表操作语法(核心重点,实操高频)

表是金仓数据库中存储数据的核心对象,表操作包括创建表、修改表、删除表、查看表结构等,这部分语法是日常开发中使用频率最高的,必须熟练掌握,同时要注意数据类型的选择和约束的设置,避免后续出现数据异常。

3.1 数据类型(基础中的基础,避坑关键)

金仓数据库支持丰富的数据类型,不同数据类型对应不同的存储需求,选择合适的数据类型不仅能节省存储空间,还能提升查询效率。以下是开发中最常用的数据类型,重点标注差异点和使用场景:

3.1.1 数值类型

数据类型存储长度取值范围使用场景
SMALLINT2字节-32768 ~ 32767存储小范围整数,如状态码、类型标识等
INTEGER4字节-2147483648 ~ 2147483647存储常规整数,如用户ID、订单ID等(最常用)
BIGINT8字节-9223372036854775808 ~ 9223372036854775807存储大范围整数,如海量数据的ID、统计计数等
NUMERIC(p,s)可变p为总位数,s为小数位数(p≤131072,s≤16383)存储精确小数,如金额、单价等(必须使用,避免精度丢失)
REAL4字节约6位十进制精度存储非精确浮点数,如科学计算、概率等
DOUBLE PRECISION8字节约15位十进制精度存储高精度非精确浮点数,如工程计算等

避坑点:存储金额、单价等需要精确计算的数据时,严禁使用REAL或DOUBLE PRECISION,必须使用NUMERIC(p,s),否则会出现精度丢失问题(如0.1+0.2≠0.3)。

3.1.2 字符类型

数据类型存储特点使用场景
CHAR(n)定长字符串,不足n位补空格,n最大为10485760存储固定长度的字符串,如身份证号、手机号等
VARCHAR(n)变长字符串,不足n位不补空格,n最大为10485760存储可变长度的字符串,如姓名、地址、描述等(最常用)
TEXT变长字符串,无长度限制存储大量文本,如文章内容、备注等

避坑点:CHAR(n)会自动补空格,查询时需要注意trim()处理,否则会出现匹配失败问题;TEXT类型虽然无长度限制,但查询效率略低于VARCHAR(n),非必要不建议使用。

3.1.3 日期时间类型

数据类型存储长度取值范围使用场景
DATE4字节4713BC ~ 5874897AD只存储日期(年-月-日),如生日、注册日期等
TIME8字节00:00:00 ~ 23:59:59.999999只存储时间(时:分:秒),如打卡时间、会议时间等
TIMESTAMP8字节4713BC ~ 5874897AD存储日期+时间(年-月-日 时:分:秒),如创建时间、更新时间等(最常用)
INTERVAL12字节-178000000年 ~ 178000000年存储时间间隔,如有效期、时间差等

避坑点:TIMESTAMP类型默认包含时区,插入数据时若不指定时区,会使用数据库当前时区;DATE和TIME类型不包含时区,建议根据业务需求选择合适的类型。

3.1.4 其他常用数据类型

  • BOOLEAN:存储布尔值(TRUE/FALSE/NULL),用于表示状态(如是否启用、是否删除等);
  • BYTEA:存储二进制数据,如图片、文件等;
  • UUID:存储通用唯一识别码,用于分布式系统中的唯一标识;
  • JSON:存储JSON格式数据,用于存储半结构化数据(如用户偏好、配置信息等)。

3.2 创建表(核心操作,含约束设置)

创建表是表操作的基础,语法中需指定表名、列名、数据类型、约束条件等,约束条件是保证数据完整性的关键,必须重点关注。

3.2.1 基本语法格式

CREATE TABLE [ IF NOT EXISTS ] 模式名.表名 (
  列名1 数据类型 [ 约束条件 ],
  列名2 数据类型 [ 约束条件 ],
  ...
  列名n 数据类型 [ 约束条件 ],
  -- 表级约束(可选)
  [ 约束名 约束类型 (列名) ]
) [ TABLESPACE 表空间名 ]; -- 可选,指定表所在的表空间

3.2.2 常用约束条件(必掌握)

约束条件用于保证表中数据的完整性和准确性,常用约束有5种,结合实例说明:

  1. 主键约束(PRIMARY KEY):唯一标识表中的每一行数据,主键列的值不能为NULL,也不能重复,一个表只能有一个主键; -- 列级主键约束 `` id INTEGER PRIMARY KEY, ```` -- 表级主键约束(推荐,可指定约束名) ``CONSTRAINT pk_user_id PRIMARY KEY (id)
  2. 非空约束(NOT NULL):指定列的值不能为NULL,确保该列必须有值; username VARCHAR(50) NOT NULL,
  3. 唯一约束(UNIQUE):指定列的值不能重复,但可以为NULL,一个表可以有多个唯一约束; -- 列级唯一约束 `` phone VARCHAR(11) UNIQUE, ```` -- 表级唯一约束(推荐,可指定约束名) ``CONSTRAINT uk_user_phone UNIQUE (phone)
  4. 检查约束(CHECK):指定列的值必须满足某个条件,用于限制列的取值范围; -- 限制年龄在18-60之间 `` age SMALLINT CHECK (age BETWEEN 18 AND 60), ```` -- 限制性别只能是男或女 ``gender CHAR(2) CHECK (gender IN ('男', '女'))
  5. 默认值约束(DEFAULT):指定列的默认值,当插入数据时未指定该列的值,会自动使用默认值; -- 默认状态为启用(1表示启用,0表示禁用) `` status SMALLINT DEFAULT 1, ```` -- 默认创建时间为当前时间 ``create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP

3.2.3 代码案例1:创建用户表(可直接运行,含完整约束)

需求:创建一个用户表(user_center_schema.user),包含用户ID、用户名、手机号、密码、年龄、性别、状态、创建时间、更新时间等字段,设置完整约束,确保数据完整性。

-- 1. 先创建模式(若已存在则跳过)
CREATE SCHEMA IF NOT EXISTS user_center_schema
AUTHORIZATION system;

-- 2. 创建用户表,设置完整约束
CREATE TABLE IF NOT EXISTS user_center_schema.user (
  id INTEGER NOT NULL, -- 非空约束
  username VARCHAR(50) NOT NULL, -- 非空约束
  phone VARCHAR(11) NOT NULL, -- 非空约束
  password VARCHAR(100) NOT NULL, -- 非空约束(存储加密后的密码)
  age SMALLINT,
  gender CHAR(2),
  status SMALLINT DEFAULT 1, -- 默认值约束:1=启用,0=禁用
  create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 默认当前时间
  update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  -- 表级约束
  CONSTRAINT pk_user_id PRIMARY KEY (id), -- 主键约束
  CONSTRAINT uk_user_username UNIQUE (username), -- 唯一约束:用户名不重复
  CONSTRAINT uk_user_phone UNIQUE (phone), -- 唯一约束:手机号不重复
  CONSTRAINT chk_user_age CHECK (age BETWEEN 18 AND 60), -- 检查约束:年龄18-60
  CONSTRAINT chk_user_gender CHECK (gender IN ('男', '女', '未知')) -- 检查约束:性别范围
) TABLESPACE sys_default; -- 使用默认表空间

-- 3. 查看表结构,确认创建成功
SELECT * FROM sys_columns WHERE table_schema = 'user_center_schema' AND table_name = 'user';

实操说明:

  • 密码字段使用VARCHAR(100),用于存储加密后的密码(如MD5、SHA256加密),避免存储明文密码;
  • create_time和update_time字段默认使用当前时间,后续可通过触发器实现update_time自动更新;
  • 约束名采用“约束类型_表名_列名”的格式,便于后续维护和修改;
  • 执行成功后,可通过sys_columns系统表查看表结构,确认字段、数据类型、约束等是否正确。

运行结果:表创建成功后,可在Kingbase Studio中查看表结构,或通过查询语句查看表信息。

3.3 修改表(新增、修改、删除列,修改约束)

实际开发中,表结构可能会根据业务需求调整,此时需要使用ALTER TABLE语句修改表结构,常用操作包括新增列、修改列、删除列、修改约束等。

3.3.1 新增列

语法格式:

ALTER TABLE 模式名.表名
ADD COLUMN [ IF NOT EXISTS ] 列名 数据类型 [ 约束条件 ] [ AFTER 已存在列名 ]; -- AFTER可选,指定列的位置

示例(可直接运行):

-- 给user_center_schema.user表新增email列,非空且唯一
ALTER TABLE user_center_schema.user
ADD COLUMN IF NOT EXISTS email VARCHAR(100) NOT NULL UNIQUE
AFTER phone; -- 新增列放在phone列后面

-- 新增remark列,用于存储备注信息,可空
ALTER TABLE user_center_schema.user
ADD COLUMN IF NOT EXISTS remark TEXT;

3.3.2 修改列

语法格式(常用修改项):

ALTER TABLE 模式名.表名
ALTER COLUMN 列名
[ TYPE 新数据类型 ] -- 修改数据类型
[ SET NOT NULL | DROP NOT NULL ] -- 修改非空约束
[ SET DEFAULT 新默认值 | DROP DEFAULT ] -- 修改默认值约束
[ RENAME TO 新列名 ]; -- 修改列名

避坑点:修改列的数据类型时,需确保该列中已有的数据能兼容新的数据类型,否则会修改失败;修改列名时,需确保没有其他对象(如视图、存储过程)依赖该列,否则会影响其他对象的正常使用。

示例(可直接运行):

-- 1. 修改age列的数据类型,从SMALLINT改为INTEGER
ALTER TABLE user_center_schema.user
ALTER COLUMN age TYPE INTEGER;

-- 2. 修改remark列,取消非空约束(若之前设置了非空)
ALTER TABLE user_center_schema.user
ALTER COLUMN remark DROP NOT NULL;

-- 3. 修改status列的默认值,从1改为0(0=禁用,1=启用)
ALTER TABLE user_center_schema.user
ALTER COLUMN status SET DEFAULT 0;

-- 4. 将remark列改名为user_remark
ALTER TABLE user_center_schema.user
ALTER COLUMN remark RENAME TO user_remark;

3.3.3 删除列

语法格式:

ALTER TABLE 模式名.表名
DROP COLUMN [ IF EXISTS ] 列名 [ CASCADE ]; -- CASCADE可选,删除依赖该列的对象

注意:删除列是不可逆操作,删除后该列的数据会彻底丢失,务必谨慎操作;若该列被其他对象(如视图、触发器)依赖,需使用CASCADE参数强制删除,否则会删除失败。

示例(可直接运行):

-- 删除user_center_schema.user表中的user_remark列
ALTER TABLE user_center_schema.user
DROP COLUMN IF EXISTS user_remark;

3.3.4 修改约束

常用操作包括添加约束、删除约束、修改约束名,语法格式如下:

-- 1. 添加约束(以检查约束为例)
ALTER TABLE 模式名.表名
ADD CONSTRAINT 约束名 约束类型 (列名);

-- 2. 删除约束
ALTER TABLE 模式名.表名
DROP CONSTRAINT [ IF EXISTS ] 约束名;

-- 3. 修改约束名
ALTER TABLE 模式名.表名
RENAME CONSTRAINT 旧约束名 TO 新约束名;

示例(可直接运行):

-- 1. 给user表添加检查约束:email必须包含@符号
ALTER TABLE user_center_schema.user
ADD CONSTRAINT chk_user_email CHECK (email LIKE '%@%');

-- 2. 删除之前的chk_user_gender约束
ALTER TABLE user_center_schema.user
DROP CONSTRAINT IF EXISTS chk_user_gender;

-- 3. 新增性别检查约束,允许未知性别
ALTER TABLE user_center_schema.user
ADD CONSTRAINT chk_user_gender_new CHECK (gender IN ('男', '女', '未知'));

-- 4. 将chk_user_email约束改名为chk_user_email_format
ALTER TABLE user_center_schema.user
RENAME CONSTRAINT chk_user_email TO chk_user_email_format;

3.4 查看表结构与表信息

常用查询语句,用于查看表结构、表约束、表统计信息等,方便排查问题:

-- 方式1:查看表的基本结构(字段名、数据类型、是否非空等)
\d 模式名.表名; -- 命令行工具使用

-- 方式2:通过系统表查询表结构(通用,图形化工具也可使用)
SELECT 
  column_name AS 列名,
  data_type AS 数据类型,
  is_nullable AS 是否可空,
  column_default AS 默认值,
  character_maximum_length AS 字符最大长度
FROM sys_columns
WHERE table_schema = 'user_center_schema' -- 模式名
  AND table_name = 'user'; -- 表名

-- 方式3:查看表的约束信息
SELECT 
  constraint_name AS 约束名,
  constraint_type AS 约束类型,
  column_name AS 关联列名
FROM sys_constraints c
JOIN sys_cons_columns cc ON c.constraint_name = cc.constraint_name
WHERE c.table_schema = 'user_center_schema'
  AND c.table_name = 'user';

-- 方式4:查看表的统计信息(行数、大小等)
SELECT 
  relname AS 表名,
  reltuples AS 估计行数,
  relpages AS 数据页数,
  pg_size_pretty(pg_relation_size(relname)) AS 表大小
FROM sys_class
WHERE relnamespace = (SELECT oid FROM sys_namespace WHERE nspname = 'user_center_schema')
  AND relname = 'user';

3.5 删除表

语法格式:

DROP TABLE [ IF EXISTS ] 模式名.表名 [ CASCADE ]; -- CASCADE可选,删除依赖该表的对象

注意:删除表是不可逆操作,删除后表中的所有数据和约束都会彻底丢失,务必谨慎操作;若该表被其他对象(如视图、存储过程)依赖,需使用CASCADE参数强制删除。

示例(可直接运行):

-- 删除user_center_schema.user表(若存在)
DROP TABLE IF EXISTS user_center_schema.user CASCADE;

四、数据操纵语法(DML,日常开发高频)

数据操纵语言(DML)用于对表中的数据进行增、删、改、查操作,是日常开发中使用频率最高的语法,重点掌握插入、更新、删除的语法规范,以及查询语句的各种用法,避免出现数据异常。

4.1 插入数据(INSERT)

插入数据是将新数据添加到表中的操作,语法格式有两种,分别适用于不同场景,同时要注意数据类型匹配和约束条件。

4.1.1 基本语法格式

  1. 指定列名插入(推荐,灵活性高,避免因表结构调整导致插入失败):

    INSERT INTO 模式名.表名 (列名1, 列名2, ..., 列名n)
    VALUES (值1, 值2, ..., 值n) [ RETURNING 列名 ];
    -- RETURNING可选,返回插入的数据
    
  2. 不指定列名插入(不推荐,表结构调整后会插入失败):

    INSERT INTO 模式名.表名
    ​​​​​​​ VALUES (值1, 值2, ..., 值n) [ RETURNING 列名 ];
    
  3. 批量插入(高效,推荐用于大量数据插入):

    INSERT INTO 模式名.表名 (列名1, 列名2, ..., 列名n)
    VALUES
    (值1-1, 值1-2, ..., 值1-n),
    (值2-1, 值2-2, ..., 值2-n),
    ...
    (值m-1, 值m-2, ..., 值m-n) [ RETURNING 列名 ];
    

4.1.2 插入数据避坑点(重点)

插入数据是新手最容易踩坑的环节,主要集中在数据类型匹配、约束条件满足、特殊字符处理三个方面,结合实操场景重点说明:

  • 数据类型严格匹配:字符串类型的值必须用单引号(' ')包裹,数值类型、布尔类型无需加引号;日期时间类型可直接使用字符串(需符合格式,如'2025-10-01 14:30:00'),也可使用函数生成(如CURRENT_TIMESTAMP);
  • 满足所有约束条件:插入数据前需确认非空列、主键列有值,唯一列无重复,检查约束符合取值范围,否则会直接报错;
  • 特殊字符处理:若字符串中包含单引号(如姓名“O'Neil”),需使用两个单引号('')转义,避免语法错误;
  • 批量插入注意事项:批量插入的每条数据需符合表结构和约束,若其中一条数据出错,整个批量插入操作会失败,建议批量插入前先测试单条数据,同时控制批量插入的条数(避免一次性插入上万条导致数据库压力过大)。

代码案例2:插入数据(单条+批量,可直接运行)

需求:基于前文创建的user_center_schema.user表,插入单条用户数据和批量用户数据,验证插入语法和约束有效性。

-- 1. 先确保用户表已创建(若已创建可跳过)
CREATE SCHEMA IF NOT EXISTS user_center_schema AUTHORIZATION system;
CREATE TABLE IF NOT EXISTS user_center_schema.user (
  id INTEGER NOT NULL,
  username VARCHAR(50) NOT NULL,
  phone VARCHAR(11) NOT NULL,
  password VARCHAR(100) NOT NULL,
  age INTEGER,
  gender CHAR(2),
  status SMALLINT DEFAULT 0,
  create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  email VARCHAR(100) NOT NULL UNIQUE,
  CONSTRAINT pk_user_id PRIMARY KEY (id),
  CONSTRAINT uk_user_username UNIQUE (username),
  CONSTRAINT uk_user_phone UNIQUE (phone),
  CONSTRAINT chk_user_age CHECK (age BETWEEN 18 AND 60),
  CONSTRAINT chk_user_gender_new CHECK (gender IN ('男', '女', '未知')),
  CONSTRAINT chk_user_email_format CHECK (email LIKE '%@%')
) TABLESPACE sys_default;

-- 2. 单条插入(指定列名,推荐)
INSERT INTO user_center_schema.user (id, username, phone, password, age, gender, email)
VALUES (1, 'zhangsan', '13800138000', 'E10ADC3949BA59ABBE56E057F20F883E', 25, '男', 'zhangsan@163.com')
RETURNING id, username, phone; -- 返回插入的关键信息,便于后续验证

-- 3. 单条插入(包含特殊字符,演示转义)
-- 姓名包含单引号,需用两个单引号转义,否则会报错
INSERT INTO user_center_schema.user (id, username, phone, password, age, gender, email)
VALUES (2, 'O''Neil', '13900139000', 'E10ADC3949BA59ABBE56E057F20F883E', 30, '男', 'oneil@qq.com');

-- 4. 批量插入(高效,推荐批量新增场景)
INSERT INTO user_center_schema.user (id, username, phone, password, age, gender, email, status)
VALUES 
  (3, 'lisi', '13700137000', 'E10ADC3949BA59ABBE56E057F20F883E', 28, '女', 'lisi@126.com', 1),
  (4, 'wangwu', '13600136000', 'E10ADC3949BA59ABBE56E057F20F883E', 22, '男', 'wangwu@gmail.com', 0),
  (5, 'zhaoliu', '13500135000', 'E10ADC3949BA59ABBE56E057F20F883E', 35, '未知', 'zhaoliu@163.com', 1)
RETURNING id, username, status;

-- 5. 测试约束有效性(故意报错,验证约束作用)
-- 以下语句会报错,可注释后运行,观察报错信息,加深对约束的理解
-- 报错原因:主键重复(id=1已存在)
-- INSERT INTO user_center_schema.user (id, username, phone, password, email)
-- VALUES (1, 'zhangsan2', '13800138001', 'E10ADC3949BA59ABBE56E057F20F883E', 'zhangsan2@163.com');
-- 报错原因:手机号重复(13800138000已存在)
-- INSERT INTO user_center_schema.user (id, username, phone, password, email)
-- VALUES (6, 'zhangsan3', '13800138000', 'E10ADC3949BA59ABBE56E057F20F883E', 'zhangsan3@163.com');
-- 报错原因:年龄不符合检查约束(小于18)
-- INSERT INTO user_center_schema.user (id, username, phone, password, age, email)
-- VALUES (6, 'zhangsan3', '13800138001', 'E10ADC3949BA59ABBE56E057F20F883E', 17, 'zhangsan3@163.com');

实操说明:

  • 密码字段存储的是MD5加密后的字符串(原始密码为123456),实际开发中需使用更安全的加密方式(如SHA256、BCrypt),严禁存储明文密码;
  • RETURNING子句可返回插入的数据,便于后续业务逻辑处理(如获取新增用户的ID),无需额外执行查询语句;
  • 故意添加的报错测试语句,建议注释后运行,观察数据库的报错信息,快速掌握约束违规的提示形式,便于后续问题排查;
  • 批量插入时,字段顺序需与VALUES后的取值顺序严格对应,否则会出现数据错位、类型不匹配等错误。

4.2 更新数据(UPDATE)

更新数据用于修改表中已存在的数据,语法需指定更新的表、列、新值,以及筛选条件(WHERE子句),核心是“精准更新”,避免误更新全表数据,这是新手最容易踩坑的点。

4.2.1 基本语法格式

UPDATE 模式名.表名
SET 列名1 = 新值1, 列名2 = 新值2, ..., 列名n = 新值n
[ WHERE 筛选条件 ] -- 必选(除非确需更新全表)
[ RETURNING 列名 ]; -- 可选,返回更新后的数据

4.2.2 关键注意事项(避坑重点)

  1. 严禁省略WHERE子句:若不写WHERE条件,会更新表中所有行的数据,造成不可逆的损失,即使需要更新全表,也建议明确写出WHERE 1=1,提醒自己是全表更新;
  2. 筛选条件要精准:建议使用主键、唯一键作为筛选条件(如id=1),确保只更新目标数据,避免因筛选条件模糊(如age>20)导致误更新;
  3. 数据类型匹配:更新后的值需与列的数据类型一致,同时满足列的约束条件(如唯一约束、检查约束),否则会更新失败;
  4. 多表关联更新:若需要根据另一张表的数据更新当前表,可使用JOIN关联,语法与查询语句类似,后续进阶部分会详细说明。

示例(可直接运行,基于前文插入的数据)

-- 1. 精准更新(根据主键更新,推荐)
-- 将id=2的用户年龄改为31,邮箱改为oneil_new@qq.com
UPDATE user_center_schema.user
SET age = 31, email = 'oneil_new@qq.com', update_time = CURRENT_TIMESTAMP
WHERE id = 2
RETURNING id, username, age, email, update_time;

-- 2. 批量更新(根据筛选条件更新,谨慎使用)
-- 将状态为0(禁用)的用户,状态改为1(启用),并更新更新时间
UPDATE user_center_schema.user
SET status = 1, update_time = CURRENT_TIMESTAMP
WHERE status = 0;

-- 3. 结合函数更新(实用场景)
-- 将所有用户的密码改为新的加密密码(原始密码123456,新加密方式SHA256)
UPDATE user_center_schema.user
SET password = SHA2('123456', 256), update_time = CURRENT_TIMESTAMP;

-- 4. 错误示范(严禁操作)
-- 以下语句会更新全表用户的用户名,造成数据混乱
-- UPDATE user_center_schema.user SET username = 'test';

-- 5. 验证更新结果
SELECT id, username, age, email, status FROM user_center_schema.user;

实操说明:update_time字段手动更新为当前时间,实际开发中可通过触发器实现“数据更新时自动更新update_time”,无需手动写SET语句,后续函数与存储过程部分会演示触发器的创建。

4.3 删除数据(DELETE)

删除数据用于删除表中不需要的数据,语法与更新数据类似,核心是“精准删除”,避免误删除全表数据,删除后数据不可逆,务必谨慎操作。

4.3.1 基本语法格式

DELETE FROM 模式名.表名
[ WHERE 筛选条件 ] -- 必选(除非确需删除全表)
[ RETURNING 列名 ]; -- 可选,返回删除的数据

4.3.2 关键注意事项(避坑重点)

  1. 严禁省略WHERE子句:与UPDATE类似,不写WHERE条件会删除表中所有数据,即使需要删除全表,也建议使用TRUNCATE语句(效率更高,且无法恢复,同样需谨慎);
  2. 筛选条件要精准:优先使用主键、唯一键作为筛选条件,确保只删除目标数据,避免误删;
  3. 关联数据删除:若当前表与其他表有关联(如外键约束),需先删除关联表中的数据,或使用ON DELETE CASCADE(级联删除),否则会删除失败;
  4. 删除前备份:重要数据删除前,建议先备份数据(如执行SELECT语句导出数据),避免删除后无法恢复。

示例(可直接运行,基于前文插入、更新的数据)

-- 1. 精准删除(根据主键删除,推荐)
-- 删除id=5的用户,返回删除的用户信息
DELETE FROM user_center_schema.user
WHERE id = 5
RETURNING id, username, phone;

-- 2. 批量删除(根据筛选条件删除,谨慎使用)
-- 删除年龄大于30的用户
DELETE FROM user_center_schema.user
WHERE age > 30;

-- 3. 清空表数据(两种方式,谨慎使用)
-- 方式1:DELETE删除全表(效率低,可恢复,适合小表)
-- DELETE FROM user_center_schema.user WHERE 1=1;

-- 方式2:TRUNCATE删除全表(效率高,不可恢复,适合大表)
-- TRUNCATE TABLE user_center_schema.user;

-- 4. 错误示范(严禁操作)
-- 以下语句会删除表中所有数据,造成数据丢失
-- DELETE FROM user_center_schema.user;

-- 5. 验证删除结果
SELECT * FROM user_center_schema.user;

补充说明:TRUNCATE与DELETE删除全表的区别:TRUNCATE会直接清空表数据,不记录日志,效率极高,但无法恢复;DELETE会逐行删除数据,记录日志,可通过事务回滚恢复,但效率较低,适合数据量较小的表。

4.4 查询数据(SELECT,核心中的核心)

查询数据是DML中使用频率最高的操作,用于从表中获取所需数据,语法灵活,可结合筛选、排序、分组、关联等操作,满足不同业务场景的需求。以下从基础查询到复杂查询,逐步讲解,嵌入实操案例。

4.4.1 基础查询(查询指定列、所有列)

-- 1. 查询指定列(推荐,避免查询无用列,提升效率)
SELECT id, username, phone, email FROM user_center_schema.user;

-- 2. 查询所有列(不推荐,若表结构调整,可能返回多余数据)
SELECT * FROM user_center_schema.user;

-- 3. 给列起别名(提升可读性,尤其适合复杂查询)
SELECT 
  id AS 用户ID,
  username AS 用户名,
  phone AS 手机号,
  age AS 年龄,
  status AS 状态
FROM user_center_schema.user;

-- 4. 去重查询(DISTINCT,去除重复数据)
-- 查询所有用户的性别,去除重复值
SELECT DISTINCT gender AS 性别 FROM user_center_schema.user;

-- 5. 查询指定行数(LIMIT,用于分页查询)
-- 查询前2条用户数据
SELECT id, username, phone FROM user_center_schema.user LIMIT 2;

-- 查询第2条到第3条数据(LIMIT 偏移量, 条数;偏移量从0开始)
SELECT id, username, phone FROM user_center_schema.user LIMIT 1, 2;

实操说明:SELECT * 虽然便捷,但会查询表中所有列,若表中包含大字段(如TEXT、BYTEA),会严重影响查询效率,实际开发中建议明确指定需要查询的列。

4.4.2 条件查询(WHERE子句,精准筛选)

结合WHERE子句,筛选出符合条件的数据,常用运算符包括:比较运算符(=、!=、>、<、>=、<=)、逻辑运算符(AND、OR、NOT)、范围运算符(BETWEEN...AND...、IN)、模糊匹配(LIKE)等。

-- 1. 比较运算符查询
-- 查询年龄等于28的用户
SELECT * FROM user_center_schema.user WHERE age = 28;
-- 查询年龄大于25且小于30的用户
SELECT * FROM user_center_schema.user WHERE age > 25 AND age < 30;

-- 2. 范围运算符查询
-- 查询年龄在22到28之间的用户(包含22和28)
SELECT * FROM user_center_schema.user WHERE age BETWEEN 22 AND 28;
-- 查询id为1、3、4的用户
SELECT * FROM user_center_schema.user WHERE id IN (1, 3, 4);

-- 3. 模糊匹配查询(LIKE)
-- % 表示任意字符(0个或多个),_ 表示单个字符
-- 查询用户名为“z”开头的用户
SELECT * FROM user_center_schema.user WHERE username LIKE 'z%';
-- 查询手机号以138开头的用户
SELECT * FROM user_center_schema.user WHERE phone LIKE '138%';
-- 查询邮箱包含“163”的用户
SELECT * FROM user_center_schema.user WHERE email LIKE '%163%';

-- 4. 空值查询(IS NULL、IS NOT NULL)
-- 查询年龄为空的用户
SELECT * FROM user_center_schema.user WHERE age IS NULL;
-- 查询年龄不为空的用户
SELECT * FROM user_center_schema.user WHERE age IS NOT NULL;

-- 5. 逻辑运算符查询
-- 查询性别为男且状态为1(启用)的用户
SELECT * FROM user_center_schema.user WHERE gender = '男' AND status = 1;
-- 查询性别为女或年龄小于25的用户
SELECT * FROM user_center_schema.user WHERE gender = '女' OR age < 25;

4.4.3 排序查询(ORDER BY,规范结果顺序)

使用ORDER BY子句对查询结果进行排序,默认升序(ASC),可指定降序(DESC),可根据多个列排序(先按第一列排序,第一列相同则按第二列排序)。

-- 1. 单列排序(升序,默认ASC,可省略)
-- 按年龄升序排序(从小到大)
SELECT id, username, age FROM user_center_schema.user ORDER BY age;

-- 2. 单列排序(降序,需指定DESC)
-- 按年龄降序排序(从大到小)
SELECT id, username, age FROM user_center_schema.user ORDER BY age DESC;

-- 3. 多列排序
-- 先按状态降序排序(启用在前),状态相同则按年龄升序排序
SELECT id, username, status, age FROM user_center_schema.user 
ORDER BY status DESC, age ASC;

-- 4. 结合条件+排序
-- 查询性别为男的用户,按年龄降序排序,取前2条
SELECT id, username, age FROM user_center_schema.user 
WHERE gender = '男' 
ORDER BY age DESC 
LIMIT 2;

4.4.4 分组查询(GROUP BY,统计分析)

使用GROUP BY子句对查询结果进行分组,结合聚合函数(如COUNT、SUM、AVG、MAX、MIN)进行统计分析,常用于报表、数据统计场景。

-- 1. 基础分组统计(按性别分组,统计每组的用户数量)
SELECT 
  gender AS 性别,
  COUNT(id) AS 用户数量, -- 统计每组的用户数(主键非空,用COUNT(id)更精准)
  AVG(age) AS 平均年龄, -- 统计每组的平均年龄
  MAX(age) AS 最大年龄, -- 统计每组的最大年龄
  MIN(age) AS 最小年龄  -- 统计每组的最小年龄
FROM user_center_schema.user
GROUP BY gender; -- 按性别分组,GROUP BY后需包含非聚合列

-- 2. 分组筛选(HAVING,筛选分组后的结果)
-- 按性别分组,统计用户数量大于1的分组
SELECT 
  gender AS 性别,
  COUNT(id) AS 用户数量
FROM user_center_schema.user
GROUP BY gender
HAVING COUNT(id) > 1; -- HAVING用于分组后筛选,WHERE用于分组前筛选

-- 3. 结合条件+分组+排序
-- 查询状态为1(启用)的用户,按性别分组,统计用户数量,按用户数量降序排序
SELECT 
  gender AS 性别,
  COUNT(id) AS 用户数量
FROM user_center_schema.user
WHERE status = 1 -- 分组前筛选:只筛选启用的用户
GROUP BY gender
HAVING COUNT(id) > 0 -- 分组后筛选:排除用户数量为0的分组
ORDER BY 用户数量 DESC;

避坑点:GROUP BY子句中,SELECT后的非聚合列(如gender)必须包含在GROUP BY中,否则会报错;HAVING与WHERE的区别:WHERE用于分组前筛选数据,HAVING用于分组后筛选分组结果。

4.4.5 多表关联查询(进阶,常用场景)

实际开发中,数据通常存储在多张表中(如用户表、订单表、角色表),需要通过关联查询获取跨表数据,金仓数据库支持INNER JOIN(内连接)、LEFT JOIN(左连接)、RIGHT JOIN(右连接)、FULL JOIN(全连接),其中INNER JOIN和LEFT JOIN最常用。

先准备关联表数据(可直接运行):

-- 1. 创建角色表(用于与用户表关联)
CREATE TABLE IF NOT EXISTS user_center_schema.role (
  role_id INTEGER NOT NULL PRIMARY KEY,
  role_name VARCHAR(50) NOT NULL UNIQUE,
  role_desc VARCHAR(200) -- 角色描述
);

-- 2. 插入角色数据
INSERT INTO user_center_schema.role (role_id, role_name, role_desc)
VALUES 
  (1, 'admin', '管理员,拥有所有权限'),
  (2, 'user', '普通用户,拥有基础权限'),
  (3, 'visitor', '访客,拥有查看权限');

-- 3. 修改用户表,新增角色ID列(与角色表关联)
ALTER TABLE user_center_schema.user
ADD COLUMN IF NOT EXISTS role_id INTEGER,
ADD CONSTRAINT fk_user_role FOREIGN KEY (role_id) REFERENCES user_center_schema.role(role_id); -- 外键约束

-- 4. 更新用户表的角色ID
UPDATE user_center_schema.user
SET role_id = CASE 
  WHEN id = 1 THEN 1 -- 张三为管理员
  WHEN id = 3 THEN 2 -- 李四为普通用户
  ELSE 3 -- 其他为访客
END;

-- 5. 多表关联查询示例
-- 方式1:INNER JOIN(内连接,只返回两张表中匹配的数据)
-- 查询用户信息及对应的角色名称(只返回有角色的用户)
SELECT 
  u.id AS 用户ID,
  u.username AS 用户名,
  u.phone AS 手机号,
  r.role_name AS 角色名称,
  r.role_desc AS 角色描述
FROM user_center_schema.user u -- 给用户表起别名u
INNER JOIN user_center_schema.role r -- 给角色表起别名r
  ON u.role_id = r.role_id; -- 关联条件:用户表的role_id = 角色表的role_id

-- 方式2:LEFT JOIN(左连接,返回左表所有数据,右表匹配不到则为NULL)
-- 查询所有用户信息及对应的角色名称(即使用户没有角色,也会返回用户信息)
SELECT 
  u.id AS 用户ID,
  u.username AS 用户名,
  r.role_name AS 角色名称,
  r.role_desc AS 角色描述
FROM user_center_schema.user u
LEFT JOIN user_center_schema.role r
  ON u.role_id = r.role_id;

-- 方式3:多表关联+条件+排序
-- 查询角色为普通用户(role_name='user')的用户信息,按年龄升序排序
SELECT 
  u.id AS 用户ID,
  u.username AS 用户名,
  u.age AS 年龄,
  r.role_name AS 角色名称
FROM user_center_schema.user u
INNER JOIN user_center_schema.role r
  ON u.role_id = r.role_id
WHERE r.role_name = 'user'
ORDER BY u.age ASC;

避坑点:多表关联时,需给表起别名(如u、r),避免列名冲突;外键约束确保了关联数据的完整性,若要删除角色表中的数据,需先删除用户表中关联该角色的记录,或设置外键级联删除(ON DELETE CASCADE)。

五、函数与存储过程(进阶,提升开发效率)

金仓数据库支持内置函数和自定义函数、存储过程,内置函数可直接使用,用于数据处理、计算、转换等;自定义函数和存储过程可封装重复的SQL逻辑,提升开发效率,减少代码冗余,适用于复杂业务场景。

5.1 常用内置函数(必掌握,实操高频)

内置函数按功能可分为字符串函数、数值函数、日期时间函数、聚合函数等,以下列出开发中最常用的函数,结合示例说明用法。

5.1.1 字符串函数

-- 1. 字符串长度(LENGTH)
SELECT username, LENGTH(username) AS 用户名长度 FROM user_center_schema.user;

-- 2. 字符串拼接(CONCAT)
SELECT CONCAT(username, '-', phone) AS 用户名_手机号 FROM user_center_schema.user;

-- 3. 字符串截取(SUBSTRING)
-- SUBSTRING(字符串, 起始位置, 截取长度),起始位置从1开始
SELECT username, SUBSTRING(username, 1, 1) AS 用户名首字符 FROM user_center_schema.user;

-- 4. 字符串大小写转换(UPPER、LOWER)
SELECT username, UPPER(username) AS 大写用户名, LOWER(username) AS 小写用户名 FROM user_center_schema.user;

-- 5. 去除空格(TRIM、LTRIM、RTRIM)
-- TRIM:去除两端空格,LTRIM:去除左端空格,RTRIM:去除右端空格
SELECT TRIM('  zhangsan  ') AS 去除两端空格, LTRIM('  zhangsan  ') AS 去除左端空格;

-- 6. 字符串替换(REPLACE)
SELECT username, REPLACE(username, 'z', 'Z') AS 替换后用户名 FROM user_center_schema.user;

5.1.2 数值函数

-- 1. 四舍五入(ROUND)
SELECT age, ROUND(age/2, 1) AS 年龄一半(保留1位小数) FROM user_center_schema.user;

-- 2. 取整(FLOOR、CEIL)
-- FLOOR:向下取整,CEIL:向上取整
SELECT age, FLOOR(age/2) AS 向下取整, CEIL(age/2) AS 向上取整 FROM user_center_schema.user;

-- 3. 绝对值(ABS)
SELECT ABS(-25) AS 绝对值;

-- 4. 随机数(RANDOM)
-- RANDOM() 返回0-1之间的随机数,乘以100取整,得到0-99之间的随机数
SELECT RANDOM(), FLOOR(RANDOM()*100) AS 0-99随机数;

-- 5. 求和、平均值(SUM、AVG)
SELECT SUM(age) AS 年龄总和, AVG(age) AS 平均年龄 FROM user_center_schema.user;

5.1.3 日期时间函数(高频)

-- 1. 获取当前日期时间(CURRENT_TIMESTAMP、NOW)
SELECT CURRENT_TIMESTAMP AS 当前日期时间, NOW() AS 当前日期时间2;

-- 2. 获取当前日期(CURRENT_DATE)
SELECT CURRENT_DATE AS 当前日期;

-- 3. 获取当前时间(CURRENT_TIME)
SELECT CURRENT_TIME AS 当前时间;

-- 4. 日期格式化(TO_CHAR)
-- TO_CHAR(日期时间, 格式化格式),常用格式:YYYY-MM-DD、HH24:MI:SS、YYYY-MM-DD HH24:MI:SS
SELECT 
  create_time,
  TO_CHAR(create_time, 'YYYY-MM-DD') AS 日期,
  TO_CHAR(create_time, 'HH24:MI:SS') AS 时间,
  TO_CHAR(create_time, 'YYYY-MM-DD HH24:MI:SS') AS 日期时间
FROM user_center_schema.user;

-- 5. 日期计算(INTERVAL)
-- 给当前日期加1天、减1个月
SELECT 
  CURRENT_DATE AS 当前日期,
  CURRENT_DATE + INTERVAL '1 day' AS1天,
  CURRENT_DATE - INTERVAL '1 month' AS1个月;

-- 6. 计算两个日期的差值(AGE)
SELECT 
  username,
  create_time,
  AGE(CURRENT_TIMESTAMP, create_time) AS 距离创建时间的间隔
FROM user_center_schema.user;

5.1.4 其他常用内置函数

-- 1. 空值处理(COALESCE)
-- COALESCE(列名, 替代值):若列值为NULL,返回替代值,否则返回列值
SELECT username, COALESCE(age, 0) AS 年龄(空值替换为0FROM user_center_schema.user;

-- 2. 条件判断(CASE WHEN)
-- 用于复杂的条件逻辑,类似程序中的if-else
SELECT 
  username,
  status,
  CASE 
    WHEN status = 1 THEN '启用'
    WHEN status = 0 THEN '禁用'
    ELSE '未知'
  END AS 状态描述
FROM user_center_schema.user;

-- 3. 加密函数(MD5、SHA2)
-- 用于密码加密,实际开发中推荐使用SHA2
SELECT MD5('123456') AS MD5加密, SHA2('123456', 256) AS SHA256加密;

5.2 自定义函数(CREATE FUNCTION)

自定义函数用于封装重复的SQL逻辑,可接收参数,返回指定类型的结果,适用于频繁使用的复杂查询、数据处理逻辑,如计算用户年龄、验证手机号格式等。

5.2.1 基本语法格式

CREATE OR REPLACE FUNCTION 模式名.函数名(参数名 参数类型)
RETURNS 返回类型 AS $$
BEGIN
  -- 函数逻辑(SQL语句)
  RETURN 结果;
END;
$$ LANGUAGE plpgsql; -- 语言类型,金仓数据库常用plpgsql

5.2.2 示例1:自定义函数(计算用户年龄)

-- 自定义函数:根据出生日期计算年龄(接收DATE类型参数,返回INTEGER类型)
CREATE OR REPLACE FUNCTION user_center_schema.calc_age(birth_date DATE)
RETURNS INTEGER AS $$
BEGIN
  -- 计算当前日期与出生日期的差值,取年份部分
  RETURN EXTRACT(YEAR FROM AGE(CURRENT_DATE, birth_date));
END;
$$ LANGUAGE plpgsql;

-- 使用自定义函数
-- 先给用户表新增出生日期列
ALTER TABLE user_center_schema.user ADD COLUMN IF NOT EXISTS birth_date DATE;
-- 更新出生日期数据
UPDATE user_center_schema.user SET birth_date = '1998-01-01' WHERE id = 1;
UPDATE user_center_schema.user SET birth_date = '2000-05-10' WHERE id = 3;
-- 调用函数计算年龄
SELECT 
  username,
  birth_date,
  user_center_schema.calc_age(birth_date) AS 计算年龄
FROM user_center_schema.user;

5.2.3 示例2:自定义函数(验证手机号格式)

-- 自定义函数:验证手机号格式(接收VARCHAR类型参数,返回BOOLEAN类型)
-- 手机号格式:11位数字,以13、14、15、17、18、19开头
CREATE OR REPLACE FUNCTION user_center_schema.check_phone(phone VARCHAR(11))
RETURNS BOOLEAN AS $$
BEGIN
  RETURN phone ~ '^1[345789]\d{9}$'; -- 正则表达式匹配
END;
$$ LANGUAGE plpgsql;

-- 使用自定义函数
SELECT 
  username,
  phone,
  user_center_schema.check_phone(phone) AS 手机号格式是否正确
FROM user_center_schema.user;

避坑点:自定义函数的参数类型、返回类型需与逻辑中的数据类型一致;函数名需唯一,若需修改函数,使用CREATE OR REPLACE FUNCTION,避免重复创建报错;正则表达式匹配时,注意语法格式(金仓数据库支持POSIX正则)。

5.3 存储过程(CREATE PROCEDURE)

存储过程与自定义函数类似,可封装复杂的SQL逻辑,但存储过程不返回值(或返回多个值),可包含更多操作(如插入、更新、删除),适用于批量处理、业务流程封装等场景(如批量新增用户、用户状态批量更新)。

5.3.1 基本语法格式

CREATE OR REPLACE PROCEDURE 模式名.存储过程名(参数名 IN/OUT 参数类型)
LANGUAGE plpgsql
AS $$
BEGIN
  -- 存储过程逻辑(可包含插入、更新、删除等操作)
END;
$$;

说明:IN表示输入参数(用于传入数据),OUT表示输出参数(用于返回数据),可同时包含多个IN、OUT参数。

5.3.2 示例:存储过程(批量新增用户)

-- 存储过程:批量新增用户(接收3个输入参数,批量插入用户数据)
CREATE OR REPLACE PROCEDURE user_center_schema.batch_insert_user(
  p_start_id IN INTEGER, -- 起始用户ID
  p_count IN INTEGER, -- 新增用户数量
  p_role_id IN INTEGER -- 角色ID
)
LANGUAGE plpgsql
AS $$
DECLARE
  i INTEGER := 1; -- 循环变量,初始值为1
BEGIN
  -- 循环插入用户数据
  WHILE i <= p_count LOOP
    INSERT INTO user_center_schema.user (
      id, username, phone, password, age, gender, email, role_id
    ) VALUES (
      p_start_id + i - 1, -- 用户ID:起始ID+循环变量-1
      'user_' || (p_start_id + i - 1), -- 用户名:user_+ID
      '138' || LPAD(i::VARCHAR, 8, '0'), -- 手机号:138+8位数字(不足补0)
      SHA2('123456', 256), -- 密码:123456加密
      18 + FLOOR(RANDOM()*12)::INTEGER, -- 年龄:18-30之间随机
      CASE WHEN i%2 = 0 THEN '女' ELSE '男' END, -- 性别:奇数男,偶数女
      'user_' || (p_start_id + i - 1) || '@163.com', -- 邮箱
      p_role_id -- 角色ID
    );
    i := i + 1; -- 循环变量自增
  END LOOP;
  -- 提示批量插入成功
  RAISE NOTICE '批量新增用户成功,共新增%个用户', p_count;
END;
$$;

-- 调用存储过程(批量新增5个用户,起始ID=10,角色ID=2)
CALL user_center_schema.batch_insert_user(10, 5, 2);

-- 验证批量插入结果
SELECT id, username, phone, role_id FROM user_center_schema.user WHERE id BETWEEN 10 AND 14;

实操说明:存储过程中使用DECLARE声明变量,使用WHILE循环实现批量插入;RAISE NOTICE用于输出提示信息,便于调试;调用存储过程使用CALL语句,传入参数即可;存储过程可包含复杂的业务逻辑,如数据校验、异常处理等,后续进阶部分可补充。

六、金仓数据库常见错误与避坑指南(重中之重)

结合前文实操,总结新手最容易遇到的错误和避坑技巧,涵盖语法、约束、数据操作等方面,帮助大家快速排查问题,避免踩坑。

6.1 语法错误(最常见)

  1. 忘记加语句结束符(分号;):所有SQL语句必须以分号结束,否则数据库会认为语句未完成,报错“syntax error at end of input”;
  2. 大小写错误:标识符(数据库名、表名、列名)大小写敏感,关键字(CREATE、SELECT)不区分大小写,若表名是小写,查询时写大写会报错“relation does not exist”;
  3. 字符串未加单引号:字符串类型的值必须用单引号包裹,若未加单引号,数据库会认为是标识符,报错“column does not exist”;
  4. 括号、逗号遗漏:创建表、插入数据时,遗漏括号、逗号,会报语法错误,建议写SQL语句时,逐行检查,尤其是复杂语句。

6.2 约束相关错误

  1. 主键重复:插入数据时,主键列的值已存在,报错“duplicate key value violates unique constraint”,需确保主键唯一;
  2. 非空约束违规:插入、更新数据时,非空列的值为NULL,报错“null value in column violates not-null constraint”,需给非空列赋值;
  3. 检查约束违规:插入、更新数据时,不符合检查约束的取值范围,报错“new row for relation violates check constraint”,需检查数据是否符合约束条件;
  4. 外键约束违规:删除、更新关联表数据时,违反外键约束,报错“update or delete on table violates foreign key constraint”,需先处理关联数据,或设置级联操作。

6.3 数据操作错误

  1. 误更新、误删除全表:省略WHERE子句,导致更新、删除全表数据,建议操作前先执行SELECT语句,验证筛选条件是否正确,再执行UPDATE、DELETE;
  2. 数据类型不匹配:插入、更新数据时,数据类型与表结构定义的类型不一致,报错“column is of type integer but expression is of type character varying”,需确保数据类型匹配;
  3. 批量插入失败:批量插入时,其中一条数据违规(如约束违规),导致整个批量插入失败,建议批量插入前先测试单条数据,或使用批量插入+异常处理;
  4. 查询效率低:使用SELECT * 查询、未加索引、多表关联未加关联条件,导致查询效率低,建议明确查询列、给常用查询字段加索引、多表关联必加关联条件。

6.4 其他常见避坑技巧

  1. 权限问题:操作数据库、表、模式时,权限不足报错,需使用拥有对应权限的账号(如system),或给当前账号授权;
  2. 中文乱码:数据库编码不是UTF8,导致中文乱码,创建数据库时需指定ENCODING = 'UTF8';
  3. 函数、存储过程报错:参数类型、返回类型不匹配,或逻辑错误,建议逐行检查逻辑,使用RAISE NOTICE输出调试信息;
  4. 数据备份:重要操作(如删除表、批量更新)前,务必备份数据,可使用COPY语句导出数据,或使用数据库备份工具。

七、总结与进阶建议

本文从实操角度出发,全面解析了金仓数据库的基础语法,涵盖数据库与模式管理、表操作、数据操纵、函数与存储过程等核心模块,嵌入3处可直接运行的代码案例,标注了常见错误和避坑技巧,确保大家看完就能上手。

金仓数据库作为国产数据库的标杆,语法遵循SQL标准,同时兼容Oracle、MySQL等主流数据库,上手难度不高,重点在于掌握细节和避坑技巧。对于新手来说,建议先熟练掌握基础语法(表操作、DML),再逐步学习函数、存储过程、触发器等进阶内容。

进阶建议

  1. 官方资源学习:登录金仓官网(www.kingbase.com.cn/)、金仓社区,查看官方文档、视频教程,获取最新的语法规范和进阶知识;
  2. 多实操练习:结合本文案例,反复练习,尝试修改案例中的参数、逻辑,熟悉语法的灵活运用,遇到报错不要慌,根据报错信息排查问题;
  3. 学习进阶内容:后续可学习金仓数据库的索引优化、事务管理、触发器、集群部署等进阶内容,提升自身能力,适应企业级场景需求;
  4. 关注版本更新:金仓数据库会不断更新迭代,新增功能和优化语法,关注版本更新日志,及时掌握新特性。

最后,国产数据库的发展离不开每一位开发者的支持,希望本文能帮助大家快速上手金仓数据库,为国产化替代贡献自己的力量。如果在实操过程中遇到问题,可留言交流,也可访问金仓官方渠道获取技术支持。