openGauss 数据库测试题
本套试题旨在全面评估与考核考生在 openGauss 数据库 环境下,针对复杂业务场景的架构设计、高级数据操纵及数据库自动化运维的核心实战能力。本试卷所有题目均基于 openGauss 数据库管理系统 的语法标准设计。部分 PL/pgSQL 结构(如存储过程的 / 结束符、触发器的 EXECUTE PROCEDURE 机制)在其他传统数据库中可能存在语法差异,以 openGauss 实际运行结果为准。 --由gemini编写
一、数据表结构参考
customer(客户表)
| 属性名 | 数据类型 | 长度 | 是否为空 | 中文描述 |
|---|---|---|---|---|
| c_id | INT | 4 | NOT NULL | 客户编号(主键) |
| c_name | VARCHAR | 100 | NOT NULL | 姓名 |
| c_hometown | VARCHAR | 30 | 籍贯 | |
| c_id_card | VARCHAR | 20 | NOT NULL | 身份证 |
| c_phone | VARCHAR | 20 | NOT NULL | 手机号 |
| c_password | VARCHAR | 20 | NOT NULL | 登录密码 |
| c_s_id | INT | 4 | NOT NULL | 社保项目编号 |
pay_card(工资卡表)
| 属性名 | 数据类型 | 长度 | 是否为空 | 中文描述 |
|---|---|---|---|---|
| p_number | CHAR | 30 | NOT NULL | 银行卡号(主键) |
| p_type | CHAR | 20 | NOT NULL | 银行卡类型 |
| p_c_id | INT | 4 | NOT NULL | 所属客户编号 |
social_security(社保表)
| 属性名 | 数据类型 | 长度 | 是否为空 | 中文描述 |
|---|---|---|---|---|
| s_id | INT | 4 | NOT NULL | 项目编号(主键) |
| s_name | VARCHAR | 100 | NOT NULL | 项目名称 |
| s_amount | INT | 4 | NOT NULL | 社保金额 |
| s_person | VARCHAR | 20 | 适用人群 | |
| s_year | INT | 4 | 社保年限 | |
| s_project | VARCHAR | 200 | 保障项目内容 | |
| s_date | DATE | 8 | 缴费日期 |
考试题型
一、编程题 1(数据库/表空间操作)
(1)使用 omm 用户登录 postgres 数据库;
(2)创建表空间 ts_temp,其 location 为 'tablespace/ts_temp';
(3)在该表空间中创建数据库 db_test;
(4)将数据库 db_test 更名为 db_exam;
(5)切换当前登录数据库为 db_exam,在 db_exam 中完成数据库对象的创建、数据的维护等操作。[请使用 SQL 语句编写]
参考答案:
-- (1) 使用 omm 用户登录 postgres 数据库
su - omm
gs_om -t start
gsql -d postgres -p 26000 -r
-- (2) 创建表空间
CREATE TABLESPACE ts_temp RELATIVE LOCATION 'tablespace/ts_temp';
--【核心代码】:
create tablespace 表空间名 relative location '表空间位置';
-- (3) 在该表空间中创建数据库
CREATE DATABASE db_test with TABLESPACE = ts_temp;
--【核心代码】:
create database 数据库名 with tablespace=表空间名;
-- (4) 数据库重命名
ALTER DATABASE db_test RENAME TO db_exam;
核心:alter database 数据库名 rename to 新数据库名;
-- (5) 切换数据库
\c db_exam
--【核心代码】:
\c 数据库名
二、编程题 2(建表)
请使用 SQL 语句,根据"数据表结构参考"完成 customer(客户表)、pay_card(工资卡表)、social_security(社保表)三张表的创建。
参考答案:
CREATE TABLE customer (
c_id INT NOT NULL,
c_name VARCHAR(100) NOT NULL,
c_hometown VARCHAR(30),
c_id_card VARCHAR(20) NOT NULL,
c_phone VARCHAR(20) NOT NULL,
c_password VARCHAR(20) NOT NULL,
c_s_id INT NOT NULL
);
CREATE TABLE pay_card (
p_number CHAR(30) NOT NULL,
p_type CHAR(20) NOT NULL,
p_c_id INT NOT NULL
);
CREATE TABLE social_security (
s_id INT NOT NULL,
s_name VARCHAR(100) NOT NULL,
s_amount INT NOT NULL,
s_person VARCHAR(20),
s_year INT,
s_project VARCHAR(200),
s_date DATE
);
INSERT INTO social_security (s_id, s_name, s_amount, s_person, s_year, s_project, s_date) VALUES
(1, '养老保险', 450, '职工', 15, '基础养老保障、个人账户养老金', '2025-06-15'),
(2, '医疗保险', 320, '职工', 20, '住院报销、门诊统筹', '2025-03-10'),
(3, '工伤保险', 120, '职工', 10, '工伤医疗、伤残补助、工亡抚恤', '2024-12-01'),
(4, '失业保险', 80, '职工', 5, '失业金发放、技能提升补贴', '2025-06-20'),
(5, '城乡居民养老', 200, '居民', 15, '基础养老金、个人账户养老', '2025-01-05');
INSERT INTO customer (c_id, c_name, c_hometown, c_id_card, c_phone, c_password, c_s_id) VALUES
(1, '张伟', '北京', '110101199501011234', '13800000001', 'pwd123456', 1),
(2, '李娜', '上海', '310101199602022345', '13900000002', 'pwd654321', 2),
(3, '王芳', '上海', '310104199403033456', '13700000003', 'pwd789012', 3),
(4, '刘强', '广州', '440101199304044567', '13600000004', 'pwd345678', 4),
(5, '张明', '深圳', '440301199705055678', '13500000005', 'pwd901234', 5);
INSERT INTO pay_card (p_number, p_type, p_c_id) VALUES
('6222021000000000001', '储蓄卡', 1),
('6228481000000000002', '信用卡', 1),
('6217001000000000003', '储蓄卡', 2),
('6222081000000000004', '储蓄卡', 3),
('6226091000000000005', '信用卡', 4);
--【核心代码】:
create table 表名
(列名1 类型 not null,
列名2 类型 not null,
......
);
三、编程题 3
使用 SQL 语句设计,为社保表添加主键,并要求社保名称取值唯一,社保年限范围在 1-20 之间(包括 1 和 20),社保适用人群默认值为"职工"。
参考答案:
ALTER TABLE social_security ADD CONSTRAINT pk_social_security PRIMARY KEY (s_id);
ALTER TABLE social_security ADD CONSTRAINT uq_s_name UNIQUE (s_name);
ALTER TABLE social_security ADD CONSTRAINT ck_s_year CHECK (s_year BETWEEN 1 AND 20);
ALTER TABLE social_security ALTER COLUMN s_person SET DEFAULT '职工';
--【核心代码】:
alter table 表名 add primary key(列名);
alter table 表名 add unique(列名);
alter table 表名 add check(列名条件);
alter table 表名 alter 列名 default '值';
alter table 表名 add foreign key(列名) references 表名(主键);
四、编程题 4
- 使用 SQL 语句设计,查询所有类型为"养老保险"且社保金额在 500 以内的社保信息。
- 使用 SQL 语句设计,查询 2025 年缴费的社保项目名称、社保金额、社保年限和缴费月份。
参考答案:
-- 1
SELECT * FROM social_security
WHERE s_name = '养老保险' AND s_amount <= 500;
s_name 和 s_project 看你insert的内容,一定要看具体insert的后的数据。
--【核心代码】:
简单查询
select 列名...,列表达式
from 表名
where 条件;
-- 2
SELECT s_name, s_amount, s_year, EXTRACT(MONTH FROM s_date) AS 缴费月份
FROM social_security
WHERE EXTRACT(YEAR FROM s_date) = 2025;
--【核心代码】:
统计查询
select 列名......,函数(列名) -- 函数包括count、sum、avg、max、min、extract
from 表名
where 条件; -- 条件中可以有extract函数,其他函数不允许
-- 提取日期中的年份:extract(year from 列名)
-- 提取日期中的月份:extract(month from 列名)
五、编程题 5
- 使用 SQL 语句设计,查询不同籍贯的客户数量,并按照客户数量降序排列。
- 使用 SQL 语句设计,查询社保金额前三名(从高到低)的项目编号、项目名称和保障项目内容。
参考答案:
-- 1
SELECT c_hometown, COUNT(*) AS 客户数量
FROM customer
GROUP BY c_hometown
ORDER BY 客户数量 DESC;
--【核心代码】:
select 列名,函数(列名) -- 本查询所有函数(列名)均一致,不能用extract函数
from 表名
where 条件
group by 列名 having 函数(列名)条件 -- group by 后面列名与select后面列名一致
order by 函数(列名) asc|desc limit n; -- asc为升序,可以省略;desc是降序,不能省略
-- 2
SELECT s_id, s_name, s_project
FROM social_security
ORDER BY s_amount DESC
LIMIT 3;
六、编程题 6
- 使用 SQL 语句设计,查询社保金额在 2000 元以下的社保项目信息,并按照社保金额降序排列。
- 使用 SQL 语句设计,查询社保项目超过 2 种的适用人群和项目数量。
参考答案:
-- 1
SELECT * FROM social_security
WHERE s_amount < 2000
ORDER BY s_amount DESC;
-- 2
SELECT s_person, COUNT(*) AS 项目数量
FROM social_security
GROUP BY s_person
HAVING COUNT(*) > 2;
七、编程题 7(查询)
- 使用 SQL 语句设计,查询客户姓名以"张"开头的客户信息,结果包含客户编号、姓名和手机号。
- 使用 SQL 语句设计,查询每种银行卡类型(p_type)对应的持卡人数,并按持卡人数降序排列。
- 使用 SQL 语句设计,查询缴费日期在 2025 年 6 月的社保项目名称和缴费日期。
参考答案:
-- 1
SELECT c_id, c_name, c_phone
FROM customer
WHERE c_name LIKE '张%';
-- 2
SELECT p_type, COUNT(*) AS 持卡人数
FROM pay_card
GROUP BY p_type
ORDER BY 持卡人数 DESC;
-- 3
SELECT s_name, s_date
FROM social_security
WHERE s_date >= '2025-06-01' AND s_date < '2025-07-01';
八、编程题 8(更新语句)
使用 SQL 语句设计,将"工伤保险"项目的社保金额变更为 1800 元。
参考答案:
UPDATE social_security
SET s_amount = 1800
WHERE s_name = '工伤保险';
--【核心代码】:
update 表名 set 列名=结果 where 列名条件;
九、编程题 9(视图 1)
使用 SQL 语句设计,创建视图 vs_shanghai,查看籍贯是上海的用户的工资卡信息,结果包括客户编号、客户姓名、银行卡类型和社保项目名称,同时给出查询视图信息的方法。
参考答案:
CREATE VIEW vs_shanghai AS
SELECT c.c_id, c.c_name, p.p_type, s.s_name
FROM customer c
JOIN pay_card p ON c.c_id = p.p_c_id
JOIN social_security s ON c.c_s_id = s.s_id
WHERE c.c_hometown = '上海';
-- 查询视图
SELECT * FROM vs_shanghai;
--【核心代码】:
连接查询
select 列名...
from 表1 join 表2 on 表1.列名=表2.列名
where 条件;
视图:
create view 视图名
as
select 列名1,列名2,......
from 表1 join 表2
on 表1.列名=表2.列名
join 表3 on 表1或表2.列名=表3.列名
where 条件
group by 列名;
select * from 视图名;
十、编程题 10(视图 2)
使用 SQL 语句设计,创建视图 vs_pension,查询社保项目名称包含"养老"的所有社保信息,结果包括项目编号、项目名称、社保金额和社保年限,同时给出查询视图信息的方法。
参考答案:
CREATE VIEW vs_pension AS
SELECT s_id, s_name, s_amount, s_year
FROM social_security
WHERE s_name LIKE '%养老%';
-- 查询视图
SELECT * FROM vs_pension;
十一、编程题 11(视图 3)
使用 SQL 语句设计,创建视图 vs_customer_pay,统计每个客户所拥有的银行卡数量,结果包括客户编号、客户姓名和卡片数量,同时给出查询视图信息的方法。
参考答案:
CREATE VIEW vs_customer_pay AS
SELECT c.c_id, c.c_name, COUNT(p.p_number) AS 卡片数量
FROM customer c
LEFT JOIN pay_card p ON c.c_id = p.p_c_id
GROUP BY c.c_id, c.c_name;
-- 查询视图
SELECT * FROM vs_customer_pay;
十二、编程题 12(存储过程 1)
使用 SQL 语句设计,创建存储过程 proc_query_customer,实现根据用户输入的客户编号,显示出该客户姓名和银行卡号,同时给出执行存储过程的方法。
参考答案:
CREATE OR REPLACE PROCEDURE proc_query_customer(IN in_c_id INT)
AS
v_name VARCHAR(100);
v_card CHAR(30);
BEGIN
-- 增加 LIMIT 1 防止返回多行报错
SELECT c_name INTO v_name FROM customer WHERE c_id = in_c_id LIMIT 1;
SELECT p_number INTO v_card FROM pay_card WHERE p_c_id = in_c_id LIMIT 1;
RAISE NOTICE '客户姓名:%,银行卡号:%', v_name, v_card;
END;
/
-- 执行存储过程
CALL proc_query_customer(1);
--【核心代码】:
create procedure 过程名
(in 参数1 类型, out 参数2 类型, out 参数3 类型)
as
begin
select 列名1,列名2 into 参数2,参数3
from 表1 join 表2 on 表1.列名=表2.列名
where 列名=参数1 and 条件;
end;
call 过程名(参数1具体值,参数2名,参数3名);
十三、编程题 13(存储过程 2)
使用 SQL 语句设计,创建存储过程 proc_query_social,实现根据用户输入的社保项目编号,显示该项目的名称和社保金额,同时给出执行存储过程的方法。
参考答案:
CREATE OR REPLACE PROCEDURE proc_query_social(IN in_s_id INT)
AS
v_name VARCHAR(100);
v_amount INT;
BEGIN
SELECT s_name, s_amount INTO v_name, v_amount
FROM social_security WHERE s_id = in_s_id;
RAISE NOTICE '项目名称:%,社保金额:%', v_name, v_amount;
END;
/
-- 执行存储过程
CALL proc_query_social(1);
十四、编程题 14(触发器 1)
使用 SQL 语句设计,创建触发器 tr40,实现在新增一位客户时,为其自动添加一条工资卡信息。自行选择合适数据,编写语句,引发触发器执行。
参考答案:
CREATE OR REPLACE FUNCTION trg_add_paycard() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO pay_card(p_number, p_type, p_c_id)
VALUES (CONCAT('CARD', NEW.c_id), '储蓄卡', NEW.c_id);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tr40
AFTER INSERT ON customer
FOR EACH ROW
EXECUTE PROCEDURE trg_add_paycard();
-- 引发触发器执行
INSERT INTO customer(c_id, c_name, c_hometown, c_id_card, c_phone, c_password, c_s_id)
VALUES (101, '李明', '北京', '110101199001011234', '13800000001', 'pwd123', 1);
--【核心代码】:
-- 插入触发器
create function ins()
return trigger
as
begin
insert into 目的表名 values(new.列名1, new.列名2......);
return new
end;
create trigger 触发器名
after insert on 表名
for each row
execute procedure ins();
insert into 表名 values(值1, 值2...);
-- 更新触发器
create function upd()
return trigger
as
begin
update 目的表名 set 列名=new.列名 where 列名=old.列名;
return new
end;
create trigger 触发器名
after update on 表名
for each row
execute procedure upd();
update 表名 set 列名=结果 where 列名条件;
十五、编程题 15(触发器 2)
使用 SQL 语句设计,创建触发器 tr41,实现在更改一位客户编号时,同步修改该客户工资卡中的所属客户编号信息。自行选择合适数据,编写语句,引发触发器执行。
参考答案:
CREATE OR REPLACE FUNCTION trg_update_paycard() RETURNS TRIGGER AS $$
BEGIN
UPDATE pay_card
SET p_c_id = NEW.c_id
WHERE p_c_id = OLD.c_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tr41
AFTER UPDATE OF c_id ON customer
FOR EACH ROW
EXECUTE PROCEDURE trg_update_paycard();
-- 引发触发器执行
UPDATE customer SET c_id = 102 WHERE c_id = 101;
十六、编程题 16(触发器 3)
使用 SQL 语句设计,创建触发器 tr42,实现在删除一位客户时,同步删除该客户名下的工资卡信息。自行选择合适数据,编写语句,引发触发器执行。
参考答案:
CREATE OR REPLACE FUNCTION trg_delete_paycard() RETURNS TRIGGER AS $$
BEGIN
DELETE FROM pay_card WHERE p_c_id = OLD.c_id;
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER tr42
AFTER DELETE ON customer
FOR EACH ROW
EXECUTE PROCEDURE trg_delete_paycard();
-- 引发触发器执行
DELETE FROM customer WHERE c_id = 102;