GaussDB数据库操作与管理
1
1.1 总结
本文档围绕 GaussDB 数据库操作与管理展开,核心涵盖数据库对象基本操作、数据字典、存储过程三大模块:数据库对象操作部分详细讲解了模式(逻辑分割对象)、用户(含三权分立权限控制)、表空间(默认 2 个系统表空间)、数据库(基于模板创建)、表(普通表分行存 / 列存、分区表支持 4 种分区方案)、索引(行存 B-Tree / 列存稀疏索引)、视图(含物化视图)、序列(自增整数生成)、同义词(对象别名)的创建、修改与删除;数据字典部分介绍了系统表(如 PG_DATABASE、PG_CLASS)、系统视图(如 DB_TABLES、DB_INDEXES)及 gsql 常用元命令;存储过程部分则阐述了匿名块、函数(需返回单值)、存储过程的语法(含变量定义、赋值、动态语句)、控制语句(条件 / 循环 / 分支)及调试方法,助力用户全面掌握 GaussDB 对象管理与存储过程开发。
1.2 思维导图(mindmap)
1.3 细总结
一、数据库对象基本操作
1. 模式(Schema)
|
类别 |
关键信息 |
操作示例 |
|
|
|
核心特性 |
- 逻辑分割数据库对象,类似操作系统目录(不可嵌套)
- 与用户弱绑定:创建用户自动生成同名模式
- 默认搜索路径:"$user",public(可通过show search_path查看) |
postgres=# show search_path;
返回:"$user",public |
|
|
|
创建 |
指定所有者:CREATE SCHEMA test_sche AUTHORIZATION test_user1;
普通创建:CREATE SCHEMA test_sche; |
- |
|
|
|
修改 / 删除 |
修改名称 / 所有者:ALTER SCHEMA test_sche RENAME TO new_sche;
级联删除:DROP SCHEMA test_sche CASCADE;(删除模式及下属对象) |
- |
|
|
2. 用户与权限
(1)用户分类与三权分立
|
用户类型 |
权限范围 |
关键说明 |
|
|
|
初始用户 |
最高权限,绕过所有权限检查 |
仅用于 DBA 管理,不建议业务使用 |
|
|
|
系统管理员 |
含 SYSADMIN 属性,默认拥有对象所有者权限(除 dbe_perf 模式) |
通过CREATE USER user2 WITH SYSADMIN;创建 |
|
|
|
普通用户 |
仅拥有被授予的权限 |
需通过 GRANT 获取对象操作权限 |
|
|
三权分立:通过gs_guc reload -N all -I all -c "enableseparationofduty=on"开启,将系统管理员的 “用户管理”“审计日志管理” 权限分立给安全管理员、审计管理员,限制过度权限。
(2)用户操作与权限管理
|
操作类型 |
语法示例 |
关键参数 |
|
|
|
创建用户 |
CREATE USER user3 WITH VALID BEGIN '2020-12-01' VALID UNTIL '2020-12-31' CONNECTION LIMIT 100 IDENTIFIED BY 'gauss@123'; |
- VALID BEGIN/UNTIL:有效期
- CONNECTION LIMIT:最大连接数(100) |
|
|
|
修改用户 |
ALTER USER user1 RENAME TO user4;
ALTER USER user1 WITH SYSADMIN; |
- 支持修改名称、添加 / 移除 SYSADMIN 属性 |
|
|
|
权限赋予 |
GRANT SELECT,INSERT ON TABLE emp1 TO user1;
GRANT CREATE,USAGE ON SCHEMA test_sche TO user1; |
支持权限:SELECT/INSERT/UPDATE/DELETE/CREATE/CONNECT 等 |
|
|
|
权限撤销 |
REVOKE INSERT ON TABLE emp1 FROM user1; |
- 对象所有者隐式权限(ALTER/DROP)无法撤销 |
|
|
3. 表空间
(1)系统表空间与特性
|
表空间名称 |
存储内容 |
对应目录 |
关键特性 |
|
|
pg_default |
系统目录、用户表 / 索引、临时表 |
$GAUSS_DATA_HOME/base/ |
默认存储位置 |
|
|
pg_global |
系统字典表 |
$GAUSS_DATA_HOME/global/ |
全集群共享 |
|
|
自定义表空间 |
用户指定对象 |
自定义目录(如 /tablespace/tbs2) |
- 支持指定最大大小(如 100G)
- 磁盘使用率达90% 时自动设为只读 |
|
(2)表空间操作
|
操作类型 |
语法示例 |
关键说明 |
|
|
|
创建 |
CREATE TABLESPACE tbs2 RELATIVE LOCATION 'tablespace/tbs2' MAXSIZE '100G';
CREATE TABLESPACE tbs3 OWNER jack LOCATION '/gauss/data/tbs3'; |
- RELATIVE:相对 GAUSS_DATA_HOME 的目录
- MAXSIZE:最大容量(unlimited 表示无上限) |
|
|
|
修改 |
ALTER TABLESPACE tbs3 RENAME TO tbs4;
ALTER TABLESPACE tbs4 RESIZE MAXSIZE UNLIMITED; |
- 支持修改名称、所有者、最大大小、表空间属性 |
|
|
|
删除 |
DROP TABLESPACE tbs4; |
需确保表空间无关联对象,否则需先删除对象 |
|
|
4. 数据库
(1)数据库基础与操作
|
类别 |
关键信息 |
语法示例 |
|
|
|
模板库 |
- template0:纯净模板,默认拷贝源
- template1:可自定义模板
- postgres:默认用户库,建议业务使用自定义库 |
- |
|
|
|
创建 |
CREATE DATABASE mydb3 WITH OWNER=jack ENCODING='UTF-8' LC_COLLATE='zh_CN.UTF-8' DBCOMPATIBILITY='ORA' TABLESPACE=tbs1 CONNECTION LIMIT=1000; |
- DBCOMPATIBILITY:兼容模式(支持 TD/ORA/MySQL/PG)
- CONNECTION LIMIT:最大并发连接(1000) |
|
|
|
修改 |
ALTER DATABASE mydb3 RENAME TO mydb4;
ALTER DATABASE mydb2 SET TABLESPACE tbs1; |
支持修改名称、所有者、默认表空间 |
|
|
|
删除 |
DROP DATABASE mydb4; |
需断开所有连接,无法删除当前连接的数据库 |
|
|
5. 表(普通表与分区表)
(1)普通表
|
类别 |
关键信息 |
语法示例 |
|
|
|
存储模型 |
- 行存表(默认):适合 OLTP,INSERT/UPDATE 效率高
- 列存表:适合 OLAP,投影高效,支持压缩(COMPRESSION=HIGH) |
行存:CREATE TABLE emp1 (id int, name varchar(20));
列存:CREATE TABLE warehouse_t3 (...) WITH (ORIENTATION=COLUMN, COMPRESSION=HIGH); |
|
|
|
特殊表 |
- 非日志表(UNLOGGED TABLE):不写预写日志
- 行级访问控制:ALTER TABLE all_data ENABLE ROW LEVEL SECURITY; |
创建非日志表:CREATE UNLOGGED TABLE warehouse_t2 (...); |
|
|
|
表操作 |
修改列:ALTER TABLE emp1 MODIFY sal NUMBER(10,2);
添加约束:ALTER TABLE emp1 ADD PRIMARY KEY (empno);
重命名:ALTER TABLE emp1 RENAME TO emp2; |
- 列存表不支持主外键约束,仅支持 NULL/NOT NULL/DEFAULT
- 行级访问控制仅普通用户生效,系统管理员不受限 |
|
|
(2)分区表
|
类别 |
关键信息 |
语法示例 |
|
|
|
分区方案 |
- 范围分区(Range):按字段范围(如日期)
- 哈希分区(Hash):按哈希值分布
- 列表分区(List):按具体值(如地区)
- 间隔分区:自动扩展范围分区 |
范围分区(VALUES LESS THAN):
CREATE TABLE pt1 (score DECIMAL(5,2)) PARTITION BY RANGE(score) PARTITION P1 VALUES LESS THAN(60); |
|
|
|
分区操作 |
增加分区:ALTER TABLE pt1 ADD PARTITION P4 VALUES LESS THAN(MAXVALUE);
删除分区:ALTER TABLE pt1 DROP PARTITION P3;
合并分区:ALTER TABLE pt1 MERGE PARTITIONS P4,P5 INTO PARTITION P3; |
- 行存表支持 4 种分区,列存表仅支持范围分区
- 无法修改分区表的 tablespace,但可修改单个分区的 tablespace |
|
|
6. 索引
(1)索引类型对比
|
存储模型 |
支持索引类型 |
核心特性 |
适用场景 |
|
|
行存表 |
B-Tree(默认)、GIN、Gist |
- B-Tree:支持唯一 / 多字段(最多 32 个)/ 部分 / 表达式索引
- GIN:倒排索引,适合数组
- Gist:适合几何 / 地理数据 |
频繁查询、WHERE 过滤、JOIN 条件 |
|
|
列存表 |
B-Tree、Psort(默认)、GIN |
- 自带 min/max 稀疏索引:减少 CU 误读取
- Psort(聚簇索引):降低离散数据 CU 交集 |
海量数据查询、范围过滤 |
|
(2)索引操作
|
操作类型 |
语法示例 |
关键说明 |
|
|
|
创建 |
唯一索引:CREATE UNIQUE INDEX t1_fn_idx ON t1(relfilenode);
分区表本地索引:CREATE INDEX pt1_id_idx ON pt1(id) LOCAL;
表达式索引:CREATE INDEX t1_upname_idx ON t1(UPPER(relname)); |
- 本地索引:每个分区对应独立索引
- 全局索引:跨分区统一索引,需指定表空间 |
|
|
|
修改 |
ALTER INDEX t1_fn_idx RENAME TO t1_fn_idx2;
ALTER INDEX t1_lttbs_idx REBUILD; |
- 支持重命名、设为不可用(UNUSABLE)、重建、修改表空间 |
|
|
|
删除 |
DROP INDEX t1_lttbs_idx;
REINDEX TABLE t1;(重建表上所有索引) |
- 重建索引可解决索引碎片问题 |
|
|
7. 视图与序列
(1)视图
|
类别 |
关键信息 |
语法示例 |
|
|
|
普通视图 |
虚拟结构,数据存于基表,基表变化视图结果同步变化 |
创建:CREATE VIEW v1 AS SELECT * FROM pg_tablespace WHERE spcname='pg_default'; |
|
|
|
物化视图 |
实际存储查询结果,需 REFRESH 刷新,无法直接更新 |
创建:CREATE MATERIALIZED VIEW mv1 TABLESPACE tbs1 AS SELECT * FROM pg_tablespace;
刷新:REFRESH MATERIALIZED VIEW mv1; |
|
|
|
视图操作 |
重命名:ALTER VIEW v1 RENAME TO v2;
修改属主:ALTER VIEW v2 OWNER TO jack;
删除:DROP MATERIALIZED VIEW mv1; |
- 普通视图删除不影响基表,物化视图删除会删除存储数据 |
|
|
(2)序列
|
操作类型 |
语法示例 |
关键说明 |
|
|
|
创建 |
CREATE SEQUENCE seq02 INCREMENT BY 1 MINVALUE 1 MAXVALUE 99999 CACHE 1 NOCYCLE; |
- INCREMENT BY:步长(默认 1)
- CACHE:预缓存序列数(默认 1)
- NOCYCLE:不循环(CYCLE 表示达最大值后重置) |
|
|
|
使用 |
SELECT NEXTVAL('seq01');(递增并返回新值)
SELECT CURRVAL('seq01');(返回最近 NEXTVAL 值)
SELECT SETVAL('seq01',1);(设置当前值) |
- 序列可作为表字段默认值:ALTER TABLE t2 ALTER tag SET DEFAULT NEXTVAL('seq01'); |
|
|
|
删除 |
DROP SEQUENCE seq01 CASCADE; |
- CASCADE:删除依赖该序列的对象 |
|
|
8. 同义词
|
操作类型 |
语法示例 |
关键说明 |
|
|
|
创建 |
CREATE SYNONYM syn_t1 FOR t1;(表同义词)
CREATE SYNONYM syn_emp FOR v_emp;(视图同义词)
CREATE SYNONYM syn_add FOR func_add_sql;(函数同义词) |
- 支持关联对象:表、视图、函数、存储过程
- 需对关联对象有对应权限(如 SELECT、CALL) |
|
|
|
使用 |
SELECT * FROM syn_emp;
SELECT syn_add(1,2); |
- 同义词仅简化访问,不改变对象权限 |
|
|
|
删除 |
DROP SYNONYM syn_add; |
- 删除同义词不影响关联对象 |
|
|
二、数据字典
1. 系统表与系统视图
(1)核心系统表
|
系统表名 |
简述 |
关键用途 |
|
|
|
PG_DATABASE |
存储可用数据库信息 |
查询数据库列表、所有者、编码 |
|
|
|
PG_NAMESPACE |
存储 Schema 相关信息 |
查询 Schema 名称、所有者 |
|
|
|
PG_ATTRIBUTE |
存储表字段信息 |
查询字段名、类型、是否非空 |
|
|
|
PG_CLASS |
存储数据库对象信息 |
查询表、索引、视图的基本属性 |
|
|
|
PG_INDEX |
存储索引部分信息 |
查询索引关联的表、字段 |
|
|
|
PG_TABLESPACE |
存储表空间信息 |
查询表空间名称、所有者、目录 |
|
|
|
PGXC_NODE |
存储集群节点信息 |
查询集群中 DN/CN 节点列表 |
|
|
|
PGXC_CLASS |
存储表的复制 / 分布信息 |
查询表的分布策略(Hash/Replication) |
|
|
(2)核心系统视图
|
系统视图名 |
简述 |
关键用途 |
|
|
|
DB_TABLES |
当前用户可访问的所有表 |
查询表名、Schema、创建时间 |
|
|
|
DB_INDEXES |
当前用户可访问的索引信息 |
查询索引名、关联表、索引类型 |
|
|
|
DB_COL_COMMENTS |
当前用户可访问表的字段注释 |
查询字段名、注释内容 |
|
|
|
DB_CONSTRAINTS |
当前用户可访问的约束信息 |
查询约束名、约束类型(主键 / 唯一) |
|
|
|
DB_SEQUENCES |
当前用户可访问的序列信息 |
查询序列名、步长、最大值 |
|
|
|
DB_PROCEDURES |
当前用户可访问的存储过程 / 函数 |
查询存储过程名、参数类型、返回值类型 |
|
|
|
DB_SYNONYMS |
当前用户可访问的同义词信息 |
查询同义词名、关联对象名 |
|
|
2. gsql 常用元命令
|
元命令 |
作用 |
示例 |
|
|
|
\l |
列出所有数据库的名称、所有者、编码 |
postgres=# \l |
|
|
|
\d |
列出当前 search_path 中模式的表 / 视图 / 序列 |
postgres=# \d |
|
|
|
\db |
列出所有表空间 |
postgres=# \db |
|
|
|
\du |
列出所有数据库用户 / 角色 |
postgres=# \du |
|
|
|
\di |
列出所有索引 |
postgres=# \di |
|
|
|
\dv |
列出所有视图 |
postgres=# \dv |
|
|
|
\d Tablename |
列出指定表的详细信息(字段、约束) |
postgres=# \d emp1 |
|
|
|
\timing |
显示 SQL 语句执行时间(毫秒) |
postgres=# \timing on |
|
|
|
\i file.sql |
执行指定 SQL 文件 |
postgres=# \i test.sql |
|
|
|
\q |
退出 gsql 客户端 |
postgres=# \q |
|
|
三、存储过程
1. 基础概念与匿名块
|
类别 |
关键信息 |
语法示例 |
|
|
|
匿名块 |
- 一次性执行,不存储
- 需包含 DECLARE(可选,变量声明)、BEGIN-END(执行语句)
- 至少 1 条执行语句(可 NULL) |
`DECLARE v_num int := 10; BEGIN DBE_OUTPUT.PRINT_LINE('v_num: ' |
|
v_num); END; /` |
|
函数 |
- 必须返回单个值
- 可在 SELECT 中调用
- 支持重载(同函数名不同参数) |
创建函数:CREATE FUNCTION func_add_sql(num1 int, num2 int) RETURN int AS BEGIN RETURN num1 + num2; END; |
|
|
|
存储过程 |
- 可返回多值 / 无返回
- 需用 CALL 调用
- 不支持在 SELECT 中使用 |
创建存储过程:CREATE PROCEDURE proc_test(i int) AS BEGIN IF i>0 THEN RAISE INFO 'i>0'; END IF; END; |
|
|
2. 变量定义与赋值
(1)变量类型与声明
|
变量类型 |
说明 |
示例 |
|
|
|
基本类型 |
支持数字(int、decimal)、字符(varchar)、日期(date)等 |
DECLARE v_id int := 100; v_name varchar(20) := 'Jerry'; |
|
|
|
%TYPE |
参考表字段类型,自动匹配字段类型 |
DECLARE v_emp_id emp.empno%TYPE;(匹配 emp 表 empno 字段类型) |
|
|
|
%ROWTYPE |
参考表行类型,存储整行数据 |
DECLARE v_emp emp%ROWTYPE;(存储 emp 表一行数据) |
|
|
|
作用域 |
- 内层块变量覆盖外层
- 外层块无法访问内层变量 |
外层 v_num=10,内层 v_num=20,内层输出 20,外层输出 10 |
|
|
(2)赋值语句
|
语法 |
说明 |
示例 |
|
|
|
variable_name := value |
value 可为常量、表达式,类型需兼容 |
v_sum := v_num1 + v_num2;
v_date := CURRENT_DATE; |
|
|
3. 动态语句
|
执行方式 |
语法 |
说明 |
|
|
|
EXECUTE IMMEDIATE |
EXECUTE IMMEDIATE dynamic_sql INTO define_var USING bind_var; |
- 执行静态动态语句
- INTO:存储查询结果
- USING:传递占位符参数 |
|
|
|
OPEN FOR |
OPEN cursor_name FOR dynamic_sql USING bind_var; |
- 执行动态查询并绑定游标
- 适合结果集为多行的场景 |
|
|
4. 控制语句
(1)条件语句
|
类型 |
语法 |
示例 |
|
|
|
IF_THEN |
IF boolean_expr THEN statements END IF; |
IF v_id > 100 THEN UPDATE emp SET sal=sal+100 WHERE empno=v_id; END IF; |
|
|
|
IF_THEN_ELSE |
IF boolean_expr THEN statements ELSE statements END IF; |
IF v_id IS NULL THEN RETURN; ELSE hp_true_filename(v_id); END IF; |
|
|
|
IF_THEN_ELSIF_ELSE |
IF boolean_expr1 THEN statements ELSIF boolean_expr2 THEN statements ELSE statements END IF; |
IF v_num=0 THEN v_res='zero'; ELSIF v_num>0 THEN v_res='positive'; ELSE v_res='negative'; END IF; |
|
|
(2)循环语句
|
类型 |
语法 |
示例 |
|
|
|
LOOP(简单) |
LOOP statements EXIT WHEN condition; END LOOP; |
LOOP v_count := v_count +1; EXIT WHEN v_count>10; END LOOP; |
|
|
|
WHILE_LOOP |
WHILE condition LOOP statements END LOOP; |
WHILE v_i < 100 LOOP INSERT INTO t VALUES(v_i); v_i := v_i+1; END LOOP; |
|
|
|
FOR_LOOP(整数) |
FOR name IN lower_bound..upper_bound BY step LOOP statements END LOOP; |
`FOR i IN 0..5 LOOP DBE_OUTPUT.PRINT_LINE('i: ' |
|
i); END LOOP;` |
(3)分支与 GOTO 语句
|
类型 |
语法 |
示例 |
|
|
|
CASE_WHEN |
CASE case_expr WHEN when_expr THEN statements ELSE statements END CASE; |
CASE v_result WHEN 1 THEN v_return:=111; WHEN 2 THEN v_return:=222; END CASE; |
|
|
|
GOTO |
GOTO label_name; <<label_name>> |
`IF v1>25 THEN GOTO pos1; END IF; <<pos1>> RAISE INFO 'v1: ' |
|
v1;` |
5. 调试与常见错误
|
常见错误 |
原因 |
解决方法 |
|
|
|
未声明变量 |
变量未在 DECLARE 部分声明 |
在 BEGIN 前的 DECLARE 块中声明变量,如DECLARE a int; |
|
|
|
PL 语法错误 |
缺少 END IF/LOOP、括号不匹配 |
检查控制语句闭合(如 IF 对应 END IF,LOOP 对应 END LOOP) |
|
|
|
SQL 语法错误 |
SELECT 语句无目标(存储过程中) |
用 INTO 存储 SELECT 结果,或用 PERFORM 丢弃结果 |
|
|
|
拼写错误 |
表名 / 字段名 / 关键字拼写错误 |
核对对象名称,使用\d 表名确认字段名 |
|
|
1.4 关键问题
问题 1:GaussDB 中三权分立的核心作用是什么?开启后系统管理员、安全管理员、审计管理员的权限有何变化?
答案:
核心作用:避免系统管理员拥有过度集中的权限(如同时掌控用户管理、审计日志管理),降低权限滥用风险,通过 “分权” 提升数据库安全性,适用于对权限管控要求高的企业级场景(如金融、政务)。
权限变化:
系统管理员:权限缩小,仅保留对自己模式的所有权限、表空间创建 / 修改 / 删除权限,失去 “用户 / 角色管理权限”“审计日志管理权限”,未被授权时无法访问其他用户的非系统模式对象;
安全管理员:承接原系统管理员的 “用户 / 角色管理权限”,负责用户创建、权限分配,但无表空间、表等对象的管理权限;
审计管理员:承接原系统管理员的 “审计日志管理权限”,负责审计日志的查看、导出与清理,无用户管理及对象操作权限。
开启方式:执行命令gs_guc reload -N all -I all -c "enableseparationofduty=on"后重启集群(gs_om -t stop && gs_om -t start)。
问题 2:GaussDB 普通表的行存与列存模型有何区别?分别适用于什么场景?创建时需注意哪些关键参数?
答案:
行存与列存模型区别:
|
对比维度 |
行存表(默认) |
列存表 |
|
|
|
存储方式 |
每行所有字段存储在一起 |
每列所有记录存储在一起 |
|
|
|
读写性能 |
INSERT/UPDATE 效率高,适合单条记录查询 |
投影(多列筛选)高效,适合海量数据聚合查询 |
|
|
|
约束支持 |
支持主外键、唯一、检查约束 |
仅支持 NULL/NOT NULL/DEFAULT 约束,支持局部聚簇(PCK) |
|
|
|
压缩特性 |
不支持压缩 |
支持压缩(如 COMPRESSION=HIGH),减少存储占用 |
|
|
|
|
|
|
|
|
适用场景:
行存表:适用于 OLTP(在线事务处理)场景,如电商订单创建、用户信息更新(需频繁插入 / 更新单条记录);
列存表:适用于 OLAP(在线分析处理)场景,如数据仓库的报表统计、海量日志分析(需多列筛选、聚合计算)。
创建关键参数:
行存表:无需特殊参数,默认即为行存,可指定约束(如PRIMARY KEY、FOREIGN KEY);
列存表:需通过WITH (ORIENTATION = COLUMN)指定,可选参数:
COMPRESSION:压缩级别(LOW/MEDIUM/HIGH);
PARTIAL CLUSTER KEY:局部聚簇键(≤2 列,基于 min/max 稀疏索引提升过滤效率)。
问题 3:GaussDB 存储过程中动态语句的两种执行方式是什么?分别适用于什么场景?请给出具体语法示例。
答案:GaussDB 存储过程中动态语句支持EXECUTE IMMEDIATE和OPEN FOR两种执行方式,区别及适用场景如下:
1. EXECUTE IMMEDIATE
适用场景:执行静态动态语句(如单条查询、非查询语句),结果集为单行或无需返回结果的场景(如创建表、更新数据)。
核心语法:EXECUTE IMMEDIATE dynamic_sql [INTO define_var] [USING bind_var];
dynamic_sql:动态 SQL 字符串;
INTO:存储查询结果(仅单行结果);
USING:传递占位符参数(避免 SQL 注入)。
示例(查询员工薪资并输出):sql CREATE OR REPLACE PROCEDURE dynamic_proc() AS
v_emp_id INT := 7788;
v_sal DECIMAL(8,2);
BEGIN
-- 动态查询语句,用USING传递参数,INTO存储结果
EXECUTE IMMEDIATE 'SELECT sal FROM emp WHERE empno = :1'
INTO v_sal
USING IN v_emp_id;
DBE_OUTPUT.PRINT_LINE('Employee ' || v_emp_id || ' Salary: ' || v_sal);
END;
CALL dynamic_proc();
2. OPEN FOR
适用场景:执行动态查询语句且结果集为多行的场景(如批量查询员工信息),需通过游标遍历结果。
核心语法:OPEN cursor_name FOR dynamic_sql [USING bind_var];
cursor_name:游标名(需先定义 REF CURSOR 类型);
dynamic_sql:动态 SQL 字符串;
USING:传递占位符参数。
示例(批量查询部门员工信息):sql CREATE OR REPLACE PROCEDURE dynamic_cursor_proc(deptno INT) AS
TYPE ref_cur_type IS REF CURSOR; -- 定义游标类型
v_cur ref_cur_type;
v_empno INT;
v_ename VARCHAR(20);
BEGIN
-- 动态绑定查询语句,用USING传递部门号参数
OPEN v_cur FOR 'SELECT empno, ename FROM emp WHERE deptno = :1'
USING IN deptno;
-- 遍历游标结果
LOOP
FETCH v_cur INTO v_empno, v_ename;
EXIT WHEN v_cur%NOTFOUND; -- 无数据时退出
DBE_OUTPUT.PRINT_LINE('Empno: ' || v_empno || ', Ename: ' || v_ename);
END LOOP;
CLOSE v_cur; -- 关闭游标
END;
CALL dynamic_cursor_proc(30); -- 查询30号部门员工
- 点赞
- 收藏
- 关注作者
评论(0)