sqlDEMO8

举报
HW_TEST 发表于 2025/11/18 22:20:27 2025/11/18
【摘要】 sqlDEMO8

--1通用SQL查询
--两张表:
create table student(sno int ,sname varchar,score int ,cno int );
create table class(cno int ,cname varchar );
insert into student values(123, 'a', 456, 1);
insert into student values(124, 'b', 546, 1);
insert into student values(125, 'c', 548, 1);
insert into student values(126, 'd', 569, 1);
insert into student values(127, 'e', 540, 1);
insert into student values(128, 'f', 536, 2);
insert into student values(129, 'g', 512, 2);
insert into student values(130, 'h', 546, 2);
insert into student values(131, 'i', 508, 2);
insert into student values(132, 'j', 456, 2);
insert into class values(1, 'class1'),(2, 'class2');
--(1)简单查询,查询学号为130的学生的名字、总成绩以及所在班级
openGauss=> select s.*,b.cname from student s,class b where sno=130 and s.cno=b.cno;
 sno | sname | score | cno | cname  
-----+-------+-------+-----+--------
 130 | h     |   546 |   2 | class2
(1 row)
--(2)查看每个班级(cno)月考总分(score)前三名,其中要求分数相同的人具有相同的编号
openGauss=> select * from (select s.sno,s.sname,s.cno,dense_rank() over(partition by s.cno order by s.score desc) as ranking,c.cname from student s join class c on s.cno=c.cno) where ranking<=3;
 sno | sname | cno | ranking | cname  
-----+-------+-----+---------+--------
 126 | d     |   1 |       1 | class1
 125 | c     |   1 |       2 | class1
 124 | b     |   1 |       3 | class1
 130 | h     |   2 |       1 | class2
 128 | f     |   2 |       2 | class2
 129 | g     |   2 |       3 | class2
(6 rows)
--------------------------------------------------------------------------------------
--(1)如何查询表的模式名和表名
oracle=> select schemaname,tablename from pg_tables where tablename='student';
 schemaname | tablename 
------------+-----------
 jack       | student
(1 row)
--(2)表查询表的所在节点 nodeoids 信息 pgxc_class
postgres=# select nodeoids from pgxc_class p join pg_class c on p.pcrelid=c.oid where c.relname='student';
  nodeoids   
-------------
 16676 16683
(1 row)
--(3)查询表所在的节点实例信息 pgxc_node(需要分布式集群场景才能查到)
postgres=# select nodeoids from pgxc_class p join pg_class c on p.pcrelid=c.oid where c.relname='student';
  nodeoids   
-------------
 16676 16683
(1 row)

postgres=# select * from pgxc_node where oid in (16676,16683);
 node_name | node_type | node_port | node_host | node_port1 | node_host1 | hostis_primary | nodeis_primary | nodeis_preferred |   node_id   | sctp_port | control_port | sctp_port1 | control_port1 | nodeis_central 
-----------+-----------+-----------+-----------+------------+------------+----------------+----------------+------------------+-------------+-----------+--------------+------------+---------------+----------------
 dn_6001   | D         |     25330 | 10.0.0.71 |      25330 | 10.0.0.71  | t              | f              | f                |  1663988763 |     25334 |        25335 |          0 |             0 | f
 dn_6002   | D         |     25332 | 10.0.0.71 |      25332 | 10.0.0.71  | t              | f              | f                | -1870446040 |     25336 |        25337 |          0 |             0 | f
(2 rows)

--------------------------------------------------------------------------------------
--(1)创建用户
oracle=> create user abc identified by 'Gauss2023';
CREATE ROLE
--(2)用户赋权
oracle=> grant select,update on jack.student to abc;
GRANT
--(3)字段权限赋予
oracle=> grant select,update(sno,sname),delete on jack.student to abc;
GRANT
--(4)字段权限回收
oracle=> revoke select,update(sno,sname),delete on jack.student from abc;
REVOKE
--(5)创建角色并赋予审计管理
oracle=> create role abc with auditadmin identified by 'Gauss2023';
CREATE ROLE
--(6)将角色授予给用户
oracle=> grant abc to jack;
GRANT ROLE
--(7)创建用户并且设置有效期
oracle=> create user abc identified by 'Gauss2023' valid begin '2023-12-15 15:00:00' valid until '2222-12-15 15:00:00';
CREATE ROLE
--------------------------------------------------------------------------------------
--4 行级别访问控制
CREATE TABLE all_data(id int, role varchar(100), data varchar(100));
CREATE USER alice PASSWORD 'Huawei12#$%';
CREATE USER bob PASSWORD 'Huawei12#$%';
CREATE USER peter PASSWORD 'Huawei12#$%';
insert into all_data values(1,'alice','abc'),(2,'bob','def'),(3,'peter','xyz');
--打开行访问控制策略开关
oracle=> alter table all_data enable row level security;
ALTER TABLE
--创建行访问控制策略,当前用户只能查看用户自身的数据
oracle=> create row level security policy rlsp_alldata on all_data using(role=current_user);
CREATE ROW LEVEL SECURITY POLICY
--切换至用户alice,执行SQL"SELECT * FROM public.all_data"
oracle=> grant select on jack.all_data to alice,bob,peter;
GRANT
oracle=> grant usage on SCHEMA jack to alice,bob,peter;
GRANT
oracle=> \c - alice
Password for user alice: 
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "oracle" as user "alice".
oracle=> select * from jack.all_data;
 id | role  | data 
----+-------+------
  1 | alice | abc
(1 row)
--删除策略
oracle=> drop row level security policy rlsp_alldata on all_data;
DROP ROW LEVEL SECURITY POLICY
--关闭行级访问策略
oracle=> alter table all_data disable row level security;
ALTER TABLE
--5 触发器
create table stu(sid int,name varchar);
create table course(cid int,name varchar);
create table selective(sid int,cid int,score int);
insert into stu values(1,'a'),(2,'b'),(3,'c');
insert into course values(1,'yuwen'),(2,'math'),(3,'english');
insert into selective values(1,1,100),(1,2,99),(1,3,98),(2,1,97),(2,2,88),(2,3,93),(3,1,91),(3,2,98),(3,3,92);
--(1)创建一个视图,把某一学生的成绩求和 
oracle=> create or replace view sum_score as select sid,sum(score) from selective group by sid;
CREATE VIEW
oracle=> select * from sum_score order by 1;
 sid | sum 
-----+-----
   1 | 297
   2 | 278
   3 | 281
(3 rows)
--(2)创建一个触发器,删除 teacher 表中某一教师数据时,同步删除org表中数据
create table teacher(id int,name varchar);
insert into teacher values (1,'a'),(2,'b');
create table org as select * from teacher;
--创建触发器函数:
create or replace function func_tri_teacher()
returns trigger
as $$
begin
  delete from org
   where id = old.id;
  return old;
end; $$ language plpgsql;
--创建触发器:
CREATE TRIGGER tri_teacher after DELETE ON teacher FOR EACH ROW execute PROCEDURE func_tri_teacher();
--验证触发器:
oracle=> select * from teacher;
 id | name 
----+------
  1 | a
  2 | b
(2 rows)

oracle=> select * from org;
 id | name 
----+------
  1 | a
  2 | b
(2 rows)

oracle=> delete from teacher where id=1;
DELETE 1
oracle=> select * from teacher ;
 id | name 
----+------
  2 | b
(1 row)

oracle=> select * from org;
 id | name 
----+------
  2 | b
(1 row)
--6 游标
create table sjh_cursor (a int,b int,c int);
insert into sjh_cursor values(1,2,3);
insert into sjh_cursor values(4,5,6);
--创建游标,使用游标从表里查询并输出2字段
create or replace procedure pro_sjh()
as
declare
  cursor c1 is select a, b
                 from sjh_cursor;
  var1 int;
  var2 int;
begin
  open c1; loop
    fetch c1 into var1,var2;
    exit when c1%notfound;
    raise notice 'sjh_cursor表a列数据为:%,b列数据为:%',var1,var2;
  end loop;
  close c1;
end;
/


oracle=> call pro_sjh();
NOTICE:  sjh_cursor表a列数据为:1,b列数据为:2
NOTICE:  sjh_cursor表a列数据为:4,b列数据为:5
 pro_sjh 
---------
 
(1 row)

--7 性能调优 
--tablea(a int,b int,c int)
create TABLE tablea(a int,b int,c int);
insert into tablea values(generate_series(1,100000),generate_series(1,100000),generate_series(1,100000));
--(1)分别创建索引,并使下列简单查询走索引:
--explain select * from tablea where a=1 and b=2;
--explain select * from tablea where b=1 and c=2;
oracle=> create TABLE tablea(a int,b int,c int);
CREATE TABLE
oracle=> insert into tablea values(generate_series(1,100000),generate_series(1,100000),generate_series(1,100000));
INSERT 0 100000
oracle=> create index idx_ab on tablea(a,b);
CREATE INDEX
oracle=> create index idx_bc on tablea(b,c);
CREATE INDEX
oracle=> analyze tablea ;
ANALYZE
oracle=> explain select * from tablea where a=1 and b=2;
                              QUERY PLAN                              
----------------------------------------------------------------------
 Index Scan using idx_bc on tablea  (cost=0.00..8.27 rows=1 width=12)
   Index Cond: (b = 2)
   Filter: (a = 1)
(3 rows)

oracle=> explain select * from tablea where b=1 and c=2;
                              QUERY PLAN                              
----------------------------------------------------------------------
 [Bypass]
 Index Scan using idx_bc on tablea  (cost=0.00..8.27 rows=1 width=12)
   Index Cond: ((b = 1) AND (c = 2))
(3 rows)
--(2)如何使 sql 不使用索引(写出三种方式)
第一:set cpu_index_tuple_cost = 100000;
oracle=> set cpu_index_tuple_cost=100000;
SET
oracle=> explain select * from tablea where a=1 and b=2;
                        QUERY PLAN                        
----------------------------------------------------------
 Seq Scan on tablea  (cost=0.00..2041.00 rows=1 width=12)
   Filter: ((a = 1) AND (b = 2))
(2 rows)
第二:ALTER INDEX INDEX_NAME UNUSABLE;
oracle=> set cpu_index_tuple_cost=0.005;
SET
oracle=> ALTER INDEX idx_ab unusable;
ALTER INDEX
oracle=> explain select * from tablea where a=1 and b=2;
                              QUERY PLAN                              
----------------------------------------------------------------------
 Index Scan using idx_bc on tablea  (cost=0.00..8.27 rows=1 width=12)
   Index Cond: (b = 2)
   Filter: (a = 1)
(3 rows)
oracle=> ALTER INDEX idx_bc unusable;
ALTER INDEX
oracle=> explain select * from tablea where a=1 and b=2;
                        QUERY PLAN                        
----------------------------------------------------------
 Seq Scan on tablea  (cost=0.00..2041.00 rows=1 width=12)
   Filter: ((a = 1) AND (b = 2))
(2 rows)
第三:SELECT /*+tablescan()*/
oracle=> explain select /*+tablescan(tablea)*/ * from tablea where a=1 and b=2;
                        QUERY PLAN                        
----------------------------------------------------------
 Seq Scan on tablea  (cost=0.00..2041.00 rows=1 width=12)
   Filter: ((a = 1) AND (b = 2))
(2 rows)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--1 通用SQL查询
create  table stu(id int ,math int ,art int ,phy int);
insert into stu values (1,60,33,66);
insert into stu values (2,61,53,86);
insert into stu values (3,70,63,66);
insert into stu values (4,90,63,76);
insert into stu values (5,59,69,79);
--1)查看每门成绩是否大于每门平均成绩;
oracle=> select id,case when math>avg(math) over() then '大于' else '小于等于' end as 'is_math_bigger?',case when art>avg(art) over() then '大于' else '小于等于' end as 'is_art_bigger?',case when phy>avg(phy) over() then '大于' else '小于等于' end as 'is_phy_bigger?' from stu;
 id | is_math_bigger? | is_art_bigger? | is_phy_bigger? 
----+-----------------+----------------+----------------
  1 | 小于等于        | 小于等于       | 小于等于
  2 | 小于等于        | 小于等于       | 大于
  3 | 大于            | 大于           | 小于等于
  4 | 大于            | 大于           | 大于
  5 | 小于等于        | 大于           | 大于
(5 rows)
--2)编写函数,获取成绩绩点,0~59给0,60~69给0.1,70~79给0.2,80~89给0.3,90~100给0.4
CREATE or REPLACE FUNCTION get_score_point(vscore INT)
RETURNS TEXT
as $$
DECLARE
BEGIN
  RETURN (
  CASE
    WHEN vscore <= 59 THEN
      '0'
    WHEN vscore <= 69 THEN
      '0.1'
    WHEN vscore <= 79 THEN
      '0.2'
    WHEN vscore <= 89 THEN
      '0.3'
    ELSE
      '0.4'
  END);
END; $$ LANGUAGE PLPGSQL;
--3)id含'3'的同学,求总的绩点,返回绩点最大的ID和总绩点
oracle=> insert into stu values (1234,99,90,99);
INSERT 0 1
oracle=> select * from stu;
  id  | math | art | phy 
------+------+-----+-----
    1 |   60 |  33 |  66
    2 |   61 |  53 |  86
    3 |   70 |  63 |  66
    4 |   90 |  63 |  76
    5 |   59 |  69 |  79
 1234 |   99 |  90 |  99
(6 rows)
oracle=> select id,get_score_point(math)+get_score_point(art)+get_score_point(phy) as sum_point from stu where id like '%3%' order by 2 desc limit 1;
  id  | sum_point 
------+-----------
 1234 |       1.2
(1 row)
--4)按照总绩点排名输出
oracle=> select id,get_score_point(math)+get_score_point(art)+get_score_point(phy) as sum_point from stu order by 2 desc;
  id  | sum_point 
------+-----------
 1234 |       1.2
    4 |       0.7
    2 |       0.4
    3 |       0.4
    5 |       0.3
    1 |       0.2
(6 rows)
--5)编写add_mask(id1,id2)函数,当id1是当前查询用户时,显示正常ID,如果不是则显示为id2.
CREATE OR REPLACE FUNCTION add_mask(id1 TEXT, id2 TEXT)
RETURNS TEXT
AS $$
DECLARE
  id3 text;
BEGIN
  SELECT USER INTO id3;
  IF id1 = id3 THEN
    RETURN 'current USER is '||id3;
  ELSE
    RETURN 'CURRENT USER IS '||id2;
  END IF;
END; $$ LANGUAGE PLPGSQL;
--------------------------------------------------------------------------------------
--2 用户权限管理
--1)创建用户user1;
oracle=> create user user1 identified by 'Gauss2023';
CREATE ROLE
--2)查看用户user1和数据库的相关权限,题目提示用pg_database和pg_roles,要求显示数据库名、用户名、数据库的权限(一定要背下来,原题,而且不要去格式美化)
SELECT a.datname, b.rolname, string_agg(a.priv_t, ',')
  from (SELECT datname, (aclexplode(COALESCE(datacl, acldefault('d' :: "char", datdba)))).grantee as grantee, (aclexplode(COALESCE(datacl, acldefault('d' :: "char", datdba)))).privilege_type as priv_t
          FROM "pg_database"
         WHERE datname not like '%template%' ) a,
       "pg_roles" b
 WHERE (a.grantee = 0 or a.grantee = b.oid)
   AND b.rolname = 'user1'
 GROUP BY a.datname, b.rolname;
--3)把表table1的select和alter权限赋给user1;
oracle=> create table table1(id int);
CREATE TABLE
oracle=> grant select,alter on table1 to user1;
GRANT
--4)查询table1的owner,要求显示表名和owner;
oracle=> select a.relname,b.usename as owner from pg_class a join pg_user b on a.relowner=b.usesysid and a.relname='table1';
 relname | owner 
---------+-------
 table1  | jack
(1 row)
--5)查询user1的表权限,要求显示表名、schema名、用户名、相关表权限;
openGauss=> select table_name,table_schema,grantee,string_agg(privilege_type,',') as privilege_type from information_schema.table_privileges where grantee='user1' group by table_name,table_schema,grantee;
 table_name | table_schema | grantee | privilege_type 
------------+--------------+---------+----------------
 table1     | jack         | user1   | SELECT,ALTER
(1 row)
--6)查询对表table1有操作权限的用户,要求显示2列:用户名、操作权限。
openGauss=> select grantee,string_agg(privilege_type,',') as privilege_type from information_schema.table_privileges where table_name='table1' group by grantee;
 grantee |                     privilege_type                      
---------+---------------------------------------------------------
 jack    | INSERT,SELECT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER
 user1   | SELECT,ALTER
(2 rows)
--3 数据库连接
--1)show max_connection;
oracle=> show max_connections;
 max_connections 
-----------------
 1000
(1 row)
--2)创建数据库带最大连接数,使用sql查出数据库的名字和最大连接;
oracle=> create database tmpdb with connection limit 1000;
CREATE DATABASE
oracle=> select datname,datconnlimit from pg_database where datname='tmpdb';
 datname | datconnlimit 
---------+--------------
 tmpdb   |         1000
(1 row)
--3)创建用户带最大连接数,使用sql查出用户的名字和最大连接;
oracle=> create user tmpuser identified by 'Gauss2023' connection limit 1000;
CREATE ROLE
oracle=> select rolname,rolconnlimit from pg_roles where rolname='tmpuser';
 rolname | rolconnlimit 
---------+--------------
 tmpuser |         1000
--4)修改数据库的最大连接数;
oracle=> create database tmpdb with connection limit 1000;
CREATE DATABASE
oracle=> alter database tmpdb connection limit 2000;
ALTER DATABASE
oracle=> select datname,datconnlimit from pg_database where datname='tmpdb';
 datname | datconnlimit 
---------+--------------
 tmpdb   |         2000
(1 row)

oracle=> drop database tmpdb;
DROP DATABASE
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--4 动态数据脱敏
--创建dev_mask和bob_mask用户。
CREATE USER dev_mask PASSWORD 'dev@1234';
CREATE USER bob_mask PASSWORD 'bob@1234';
--创建一个表tb_for_masking
CREATE TABLE tb_for_masking(col1 text, col2 text, col3 text);
--创建资源标签标记敏感列col1
oracle=> create resource label rl_col1 add column(tb_for_masking.col1);
CREATE RESOURCE LABEL
--创建资源标签标记敏感列col2
oracle=> create resource label rl_col2 add column(tb_for_masking.col2);
CREATE RESOURCE LABEL
--对访问敏感列col1的操作创建脱敏策略
oracle=> create masking policy mp_col1 creditcardmasking on label(rl_col1);
CREATE MASKING POLICY
--为脱敏策略maskpol1添加描述
oracle=> alter masking policy mp_col1 comments '这是col1的脱敏策略';
ALTER MASKING POLICY
--修改脱敏策略maskpol1,新增一项脱敏方式
oracle=> alter masking policy mp_col1 add fullemailmasking on label(rl_col1);
ALTER MASKING POLICY
--修改脱敏策略maskpol1,移除一项脱敏方式
oracle=> alter masking policy mp_col1 remove fullemailmasking on label(rl_col1);
ALTER MASKING POLICY
--修改脱敏策略maskpol1,修改一项脱敏方式
oracle=> alter masking policy mp_col1 modify maskall on label(rl_col1);
ALTER MASKING POLICY
--修改脱敏策略maskpol1使之仅对用户dev_mask和bob_mask,客户端工具为psql和gsql,IP地址为'10.20.30.40', '127.0.0.0/24'场景生效。
oracle=> alter masking policy mp_col1 modify (filter on roles ('dev_mask','bob_mask'),app(psql,gsql),ip('10.20.30.40', '127.0.0.0/24'));
ALTER MASKING POLICY
--修改脱敏策略maskpol1,使之对所有用户场景生效
oracle=> alter masking policy mp_col1 drop filter;
ALTER MASKING POLICY
--禁用脱敏策略maskpol1
oracle=> alter masking policy mp_col1 disable;
ALTER MASKING POLICY
oracle=> select * from gs_masking_policy;
 polname |    polcomments     |         modifydate         | polenabled 
---------+--------------------+----------------------------+------------
 mp_col1 | 这是col1的脱敏策略 | 2023-12-18 15:09:08.142365 | f
(1 row)

oracle=> select * from gs_policy_label;
 labelname | labeltype | fqdnnamespace | fqdnid | relcolumn | fqdntype 
-----------+-----------+---------------+--------+-----------+----------
 rl_tbl    | resource  |         20900 |  23209 |           | table
 rl_col1   | resource  |         20900 |  23787 | col1      | column
 rl_col2   | resource  |         20900 |  23787 | col2      | column
(3 rows)
oracle=> drop masking policy mp_col1;
DROP MASKING POLICY
oracle=> drop resource label rl_tbl,rl_col1,rl_col2;
DROP RESOURCE LABEL


create table student (id int,vdate timestamp);
--1)编写存储过程,输入个数,生成student,id从100000开始,starttime是当前时间;
CREATE OR REPLACE PROCEDURE ins_student(num int)
AS
DECLARE
  id    int := 100000;
  var   int;
  count int;
BEGIN
  FOR var IN 1.. num LOOP
    INSERT INTO "student"
    VALUES
      (id, now());
    id := id+1;
  END LOOP;
  SELECT count(*) INTO count
    from student;
  raise info '已插入%行,目前student表共有%行',num,count;
END;
/
--2)调用存储过程,生成90000个;
oracle=> call ins_student(90000);
INFO:  已插入90000行,目前student表共有90000行
 ins_student 
-------------
 
(1 row)
--3)查看生成了多少个。
oracle=> select count(*) from student;
 count 
-------
 90000
(1 row)


--su(id,first_name,family_name,sexmark,grade) id是主键
create table su(id int primary key,first_name varchar,family_name varchar,sexmark varchar,grade int);
insert into su values(1,'alice','bob','A',99),(2,'cid','data','B',88),(3,'opengauss','mpp','C',90),(4,'second','nice','D',83),(5,'tmpsec','good','E',96);
--(1)family_name跟first_name用'.'拼接,要求首字母大写
oracle=> select id,initcap(family_name||'.'||first_name),sexmark,grade from su;
 id |    initcap    | sexmark | grade 
----+---------------+---------+-------
  1 | Bob.Alice     | A       |    99
  2 | Data.Cid      | B       |    88
  3 | Mpp.Opengauss | C       |    90
  4 | Nice.Second   | D       |    83
  5 | Good.Tmpsec   | E       |    96
(5 rows)
--(2)firstname里面以'sec'开头的,给出判断结果
oracle=> select id,first_name,case when first_name like 'sec%' then 'T' else 'F' end as 'begin_with_sec?',family_name,sexmark,grade from jack.su;
 id | first_name | begin_with_sec? | family_name | sexmark | grade 
----+------------+-----------------+-------------+---------+-------
  1 | alice      | F               | bob         | A       |    99
  2 | cid        | F               | data        | B       |    88
  3 | opengauss  | F               | mpp         | C       |    90
  4 | second     | T               | nice        | D       |    83
  5 | tmpsec     | F               | good        | E       |    96
(5 rows)
--(3)根据grade做排序,生成连续的排序值,其中要求分数相同的人具有相同的编号,显示包含ID、first_name、family_name
oracle=> select id,first_name,family_name,grade,dense_rank() over(partition by 1 order by grade desc) from jack.su;
 id | first_name | family_name | grade | dense_rank 
----+------------+-------------+-------+------------
  1 | alice      | bob         |    99 |          1
  5 | tmpsec     | good        |    96 |          2
  3 | opengauss  | mpp         |    90 |          3
  2 | cid        | data        |    88 |          4
  4 | second     | nice        |    83 |          5
(5 rows)
--(4)merge into ,根据ID判断,如果存在id=1则把sexmask字段改成'F',如果不存在插入下列数据:(2,'XX','XX','XX',98)
oracle=> select * from su order by 1;
 id | first_name | family_name | sexmark | grade 
----+------------+-------------+---------+-------
  1 | alice      | bob         | A       |    99
  2 | cid        | data        | B       |    88
  3 | opengauss  | mpp         | C       |    90
  4 | second     | nice        | D       |    83
  5 | tmpsec     | good        | E       |    96
(5 rows)

oracle=> delete from su where id=2;
DELETE 1
oracle=> merge into su using (select 2 id) b on (su.id=b.id) when matched then update set sexmark='F' when not matched then insert values (2,'XX','XX','XX',98);
MERGE 1
oracle=> select * from su order by 1;
 id | first_name | family_name | sexmark | grade 
----+------------+-------------+---------+-------
  1 | alice      | bob         | A       |    99
  2 | XX         | XX          | XX      |    98
  3 | opengauss  | mpp         | C       |    90
  4 | second     | nice        | D       |    83
  5 | tmpsec     | good        | E       |    96
(5 rows)

oracle=> merge into su using (select 2 id) b on (su.id=b.id) when matched then update set sexmark='F' when not matched then insert values (2,'XX','XX','XX',98);
MERGE 1
oracle=> select * from su order by 1;
 id | first_name | family_name | sexmark | grade 
----+------------+-------------+---------+-------
  1 | alice      | bob         | A       |    99
  2 | XX         | XX          | F       |    98
  3 | opengauss  | mpp         | C       |    90
  4 | second     | nice        | D       |    83
  5 | tmpsec     | good        | E       |    96
(5 rows)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
create table student(student_id int,math int,phy int,art int,m2 int);
create table weight(weight_no int ,math numeric(3,1),phy numeric(3,1),art numeric(3,1),m2 numeric(3,1));
insert into student values(1,80,70,87,90);
insert into student values(2,80,70,87,90);
insert into student values(3,81,80,69,96);
insert into student values(4,89,86,89,93);
insert into student values(5,84,87,97,90);
insert into student values(6,89,79,88,91);
insert into student values(7,83,78,84,92);
insert into student values(8,84,79,89,93);
insert into student values(9,85,76,87,91);
insert into student values(10,90,90,84,93);
insert into weight values(1,0.4,0.3,0.2,0.1);
insert into weight values(2,0.1,0.2,0.3,0.4);
--(1)求math、phy总成绩以及art、m2的总成绩:
openGauss=> select student_id,math+phy as sum_math_phy,art+m2 as sum_art_m2 from student ;
 student_id | sum_math_phy | sum_art_m2 
------------+--------------+------------
          1 |          150 |        177
          2 |          150 |        177
          3 |          161 |        165
          4 |          175 |        182
          5 |          171 |        187
          6 |          168 |        179
          7 |          161 |        176
          8 |          163 |        182
          9 |          161 |        178
         10 |          180 |        177
(10 rows)
--(2)根据维度表,按照两种加权算法计算出每个学生的加权成绩,展示包含student_id,weight_sum,单个学生加权成绩可以两行输出
oracle=> select a.student_id,a.math*b.math+a.phy*b.phy+a.art*b.art+a.m2*b.m2 as sum_point_score from student a,weight b;
 student_id | sum_point_score 
------------+-----------------
          1 |            79.4
          1 |            84.1
          2 |            79.4
          2 |            84.1
          3 |            79.8
          3 |            83.2
          4 |            88.5
          4 |            90.0
          5 |            88.1
          5 |            90.9
          6 |            86.0
          6 |            87.5
          7 |            82.6
          7 |            85.9
          8 |            84.4
          8 |            88.1
          9 |            83.3
          9 |            86.2
         10 |            89.1
         10 |            89.4
(20 rows)
--(3)根据维度表,按照两种加权算法计算出每个学生的加权成绩,展示包含student_id,weight_sum,单个学生加权成绩要求一行输出
--输出列名结果如下:
 student_id | weight1_sum | weight2_sum

oracle=> select a.student_id,a.math*b.math+a.phy*b.phy+a.art*b.art+a.m2*b.m2 as weight1_sum,a.math*c.math+a.phy*c.phy+a.art*c.art+a.m2*c.m2 as weight2_sum from student a,(select * from weight where weight_no=1) b,(select * from weight where weight_no=2) c;
 student_id | weight1_sum | weight2_sum 
------------+-------------+-------------
          1 |        79.4 |        84.1
          2 |        79.4 |        84.1
          3 |        79.8 |        83.2
          4 |        88.5 |        90.0
          5 |        88.1 |        90.9
          6 |        86.0 |        87.5
          7 |        82.6 |        85.9
          8 |        84.4 |        88.1
          9 |        83.3 |        86.2
         10 |        89.1 |        89.4
(10 rows)
--(4)对两种加权总成绩按排序。要求输出格式student_id,weight1_sum、rank1、weight2_sum、rank2,
--RANK1和RANK2分别按weight1_sum,weight2_sum倒序,整体结果按student_id进行正序排序
select student_id, weight1_sum, dense_rank() over(partition by 1 order by weight1_sum desc) as rank1, weight2_sum, dense_rank() over(partition by 1 order by weight2_sum desc) as rank2
  from (select s.student_id, w1.weight1_sum, w2.weight2_sum
          from student s
          join (select s.student_id, s.math * w.math + s.phy * w.phy + s.art * w.art + s.m2 * w.m2 as weight1_sum
          from student s, weight w
         where w.weight_no = 1 ) w1 on s.student_id = w1.student_id
          join (select s.student_id, s.math * w.math + s.phy * w.phy + s.art * w.art + s.m2 * w.m2 as weight2_sum
          from student s, weight w
         where w.weight_no = 2 ) w2 on s.student_id = w2.student_id )
 order by 1;
 
 student_id | weight1_sum | rank1 | weight2_sum | rank2 
------------+-------------+-------+-------------+-------
          1 |        79.4 |     9 |        84.1 |     8
          2 |        79.4 |     9 |        84.1 |     8
          3 |        79.8 |     8 |        83.2 |     9
          4 |        88.5 |     2 |        90.0 |     2
          5 |        88.1 |     3 |        90.9 |     1
          6 |        86.0 |     4 |        87.5 |     5
          7 |        82.6 |     7 |        85.9 |     7
          8 |        84.4 |     5 |        88.1 |     4
          9 |        83.3 |     6 |        86.2 |     6
         10 |        89.1 |     1 |        89.4 |     3
(10 rows)

--3 账本数据库
--创建防篡改模式ledgernsp。
oracle=> create schema ledgernsp with blockchain;
CREATE SCHEMA
--创建防篡改用户表ledgernsp.usertable。
oracle=> create table ledgernsp.usertable(id int,name varchar);
CREATE TABLE
--校验指定防篡改用户表的表级数据hash值与其对应历史表hash一致性。
oracle=> select pg_catalog.ledger_hist_check('ledgernsp','usertable');
 ledger_hist_check 
-------------------
 t
(1 row)
--校验指定防篡改用户表对应的历史表hash与全局历史表对应的relhash一致性。
oracle=> select pg_catalog.ledger_gchain_check('ledgernsp','usertable');
 ledger_gchain_check 
---------------------
 t
(1 row)
--4 安全审计
--(1)用SQL查看是否打开
oracle=> select name,setting from pg_settings where name='audit_enabled';
     name      | setting 
---------------+---------
 audit_enabled | on
(1 row)
--(2)用SQL查看日志存储最大空间
oracle=> select name,setting from pg_settings where name='audit_space_limit';
       name        | setting 
-------------------+---------
 audit_space_limit | 1048576
(1 row)
--(3)查看过去一天所有产生审计日志的总数。要用now()
oracle=> select * from pg_query_audit(now()-interval '1day',now());
--(4)查过去一天user1这个用户登录postgres数据库,要用now()
oracle=> select * from pg_query_audit(now()-interval '1day',now()) where username='user1';
--(5)删除指定时间段的审计日志。
oracle=> select * from pg_delete_audit('2023-12-01','2023-12-20');
 pg_delete_audit 
-----------------
 
(1 row)
--(6)删除数据库DB2;级联删除用户user1。
oracle=> drop database mysql;
DROP DATABASE
oracle=> drop user user1 cascade;
DROP ROLE

--7 性能优化
--test(id、kemu、classID、grade),里面8万条数据
CREATE TABLE test(id int,kemu VARCHAR,classid int,grade int);
INSERT INTO test VALUES(generate_series(1,80000),concat('kemu',cast(ceil(random()*10) as integer)),ceil(random()*10),ceil(random()*100));
INSERT INTO test VALUES(generate_series(800001,800010),concat('kemu',cast(ceil(random()*10) as integer)),10,generate_series(101,110));
--1、查10班级里面kemu1最低分是多少,要保障走索引
oracle=> create index idx_kemu_grade on test(kemu,grade);
CREATE INDEX
oracle=> analyze test;
ANALYZE
oracle=> explain select min(grade) from test where kemu='kemu1' and classid=10;
                                          QUERY PLAN                                          
----------------------------------------------------------------------------------------------
 Result  (cost=2.97..2.98 rows=1 width=0)
   InitPlan 1 (returns $0)
     ->  Limit  (cost=0.00..2.97 rows=1 width=4)
           ->  Index Scan using idx_kemu_grade on test  (cost=0.00..2353.47 rows=792 width=4)
                 Index Cond: (((kemu)::text = 'kemu1'::text) AND (grade IS NOT NULL))
                 Filter: (classid = 10)
(6 rows)
oracle=> select min(grade) from test where kemu='kemu1' and classid=10;
 min 
-----
   1
(1 row)
--2、10班级同一科目成绩比9班级最高分高的同学(本题只做逻辑参考,非原题,原题记不住了)
oracle=> select a.*,b.kemu as B_kemu,b.grade as B_grade from test a,(select kemu,max(grade) as grade from test where classid=9 group by kemu) b where a.kemu=b.kemu and a.grade>b.grade order by 1;
   id   | kemu  | classid | grade | B_kemu | B_grade 
--------+-------+---------+-------+--------+---------
 800001 | kemu8 |      10 |   101 | kemu8  |     100
 800002 | kemu9 |      10 |   102 | kemu9  |     100
 800003 | kemu4 |      10 |   103 | kemu4  |     100
 800004 | kemu4 |      10 |   104 | kemu4  |     100
 800005 | kemu4 |      10 |   105 | kemu4  |     100
 800006 | kemu6 |      10 |   106 | kemu6  |     100
 800007 | kemu3 |      10 |   107 | kemu3  |     100
 800008 | kemu8 |      10 |   108 | kemu8  |     100
 800009 | kemu7 |      10 |   109 | kemu7  |     100
 800010 | kemu6 |      10 |   110 | kemu6  |     100
(10 rows)

--1 存储过程:
oracle=> create table student (sid int,math int,art int,phy int,music int);
CREATE TABLE
oracle=> insert into student values (1,88,66,81,91),(2,33,44,55,66),(3,22,33,45,43);
INSERT 0 3
--(1)输入学号,返回对应的总成绩
oracle=> CREATE OR REPLACE PROCEDURE get_sum_score(vid int)
oracle-> AS
oracle$> DECLARE
oracle$>   vscore INT;
oracle$> BEGIN
oracle$>   SELECT math + art + phy + music INTO vscore
oracle$>     FROM "student"
oracle$>    WHERE sid = vid;
oracle$>   raise info 'sid为%的学生的总成绩为%',vid,vscore;
oracle$> END;
oracle$> /
CREATE PROCEDURE

oracle=> call get_sum_score(1);
INFO:  sid为1的学生的总成绩为326
 get_sum_score 
---------------
 
(1 row)
--(2)对于学生每科成绩,0-59,绩点0,60-69,绩点0.1, 70-79,绩点0.2,80-89,绩点0.3, 90-100,绩点0.4,给出学号和科目,返回对应的绩点(本题只做逻辑参考,非原题,原题记不住了)
oracle=> CREATE OR REPLACE PROCEDURE get_sid_point(id int)
oracle-> AS
oracle$> DECLARE
oracle$>   math_score  DECIMAL(3, 1);
oracle$>   art_score   DECIMAL(3, 1);
oracle$>   phy_score   DECIMAL(3, 1);
oracle$>   music_score DECIMAL(3, 1);
oracle$>   vid         int;
oracle$> BEGIN
oracle$>   SELECT sid,
oracle$>          CASE
oracle$>            WHEN math <= 60 THEN
oracle$>              0
oracle$>            WHEN math < 70 THEN
oracle$>              0.1
oracle$>            WHEN math < 80 THEN
oracle$>              0.2
oracle$>            WHEN math < 90 THEN
oracle$>              0.3
oracle$>            WHEN math <= 100 THEN
oracle$>              0.4
oracle$>          END as math_score,
oracle$>          CASE
oracle$>            WHEN art <= 60 THEN
oracle$>              0
oracle$>            WHEN art < 70 THEN
oracle$>              0.1
oracle$>            WHEN art < 80 THEN
oracle$>              0.2
oracle$>            WHEN art < 90 THEN
oracle$>              0.3
oracle$>            WHEN art <= 100 THEN
oracle$>              0.4
oracle$>          END as art_score,
oracle$>          CASE
oracle$>            WHEN phy <= 60 THEN
oracle$>              0
oracle$>            WHEN phy < 70 THEN
oracle$>              0.1
oracle$>            WHEN phy < 80 THEN
oracle$>              0.2
oracle$>            WHEN phy < 90 THEN
oracle$>              0.3
oracle$>            WHEN phy <= 100 THEN
oracle$>              0.4
oracle$>          END as phy_score,
oracle$>          CASE
oracle$>            WHEN music <= 60 THEN
oracle$>              0
oracle$>            WHEN music < 70 THEN
oracle$>              0.1
oracle$>            WHEN music < 80 THEN
oracle$>              0.2
oracle$>            WHEN music < 90 THEN
oracle$>              0.3
oracle$>            WHEN music <= 100 THEN
oracle$>              0.4
oracle$>          END as music_score INTO vid,
oracle$>          math_score,
oracle$>          art_score,
oracle$>          phy_score,
oracle$>          music_score
oracle$>     FROM "student"
oracle$>    WHERE sid = id;
oracle$>   raise info 'sid为%的学生的绩点为math->%,art->%,phy->%,music->%',vid,math_score,art_score,phy_score,music_score;
oracle$> END;
oracle$> /
CREATE PROCEDURE
oracle=> call get_sid_point(1);
INFO:  sid为1的学生的绩点为math->0.3,art->0.1,phy->0.3,music->0.4
 get_sid_point 
---------------
 
(1 row)

===================================================================================================================================================
--2 性能调优:(本题只做逻辑参考,非原题,原题记不住了,考试中的大概率没有这么复杂)
oracle=> create table student (sid int primary key,name varchar,classid int);
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "student_pkey" for table "student"
CREATE TABLE
oracle=> insert into student values (1,'a',202201),(2,'b',202201),(3,'c',202201),(4,'d',202202),(5,'e',202202),(6,'f',202202),(7,'g',202203),(8,'h',202203),(9,'i',202203);
INSERT 0 9
oracle=> create table score1 (sid int,kemu varchar,score int,foreign key(sid) references student(sid));
CREATE TABLE
oracle=> create table score2 (sid int,kemu varchar,score int,foreign key(sid) references student(sid));
CREATE TABLE
oracle=> insert into score1 values (1,'语文',99),(1,'数学',98),(1,'英语',97),(2,'语文',97),(2,'数学',91),(2,'英语',92),(3,'语文',91),(3,'数学',93),(3,'英语',88),(4,'语文',93),(4,'数学',92),(4,'英语',92),(5,'语文',94),(5,'数学',90),(5,'英语',79),(6,'语文',89),(6,'数学',90),(6,'英语',77),(7,'语文',83),(6,'数学',96),(6,'英语',78),(7,'语文',33),(7,'数学',77),(7,'英语',77),(8,'语文',88),(8,'数学',88),(8,'英语',88),(9,'语文',99),(9,' 数学',98),(9,'英语',96);
INSERT 0 30
oracle=> insert into score2 values (1,'语文',99),(1,'数学',94),(1,'英语',100),(2,'语文',100),(2,'数学',91),(2,'英语',92),(3,'语文',91),(3,'数学',93),(3,'英语',92),(4,'语文',93),(4,'数学',92),(4,'英语',92),(5,'语文',94),(5,'数学',94),(5,'英语',79),(6,'语文',89),(6,'数学',94),(6,'英语',68),(7,'语文',83),(6,'数学',96),(6,'英语',78),(7,'语文',33),(7,'数学',68),(7,'英语',68),(8,'语文',92),(8,'数学',92),(8,'英语',92),(9,'语文',99),(9,'数学',94),(9,'英语',96);
INSERT 0 30
--1,三个表,student和score1, score2表,查202201班级和202202班级所有人语文成绩前5的记录,第一个查询要使用union, 第二个查询是对第一个的优化
 --QUERY 1
select *
  FROM (SELECT a.sid, a.name, a.classid, b.kemu, b.score
          FROM "student" a
          JOIN "score1" b ON a.sid = b.sid
         WHERE a.classid in(202201, 202202)
           and b.kemu = '语文'
         order by b.score desc
         limit 5 )
UNION ALL
select *
  FROM (SELECT a.sid, a.name, a.classid, b.kemu, b.score
          FROM "student" a
          JOIN "score2" b ON a.sid = b.sid
         WHERE a.classid in(202201, 202202)
           and b.kemu = '语文'
         order by b.score desc
         limit 5 )
 order by score desc
 LIMIT 5;
 --QUERY 2
WITH CombinedScores AS
         (SELECT a.sid, a.name, a.classid, b.score
            FROM "student" a
            JOIN score1 b ON a.sid = b.sid
           WHERE classid IN('202201', '202202')
             and b.kemu = '语文' UNION ALL
             SELECT a.sid, a.name, a.classid, b.score
                  FROM "student" a
                  JOIN score2 b ON a.sid = b.sid
                 WHERE classid IN('202201', '202202')
                   and b.kemu = '语文')
SELECT sid, name, score
  FROM CombinedScores
 ORDER BY score DESC
 LIMIT 5;

--2,找202201和202202年级相同的科目,202201的成绩在score2中不存在的成绩,每一个查询要求使用not in, 第二个查询是对第一个的优化
select t202201.*
  from (SELECT a.sid, a.name, a.classid, b.kemu, b.score
          FROM "student" a
          JOIN "score1" b ON a.sid = b.sid
                         AND a.classid = 202201
        UNION ALL
        SELECT a.sid, a.name, a.classid, b.kemu, b.score
          FROM "student" a
          JOIN "score2" b ON a.sid = b.sid
                         AND a.classid = 202201) t202201,(SELECT a.sid, a.name, a.classid, b.kemu, b.score
                                            FROM "student" a
                                            JOIN "score1" b ON a.sid = b.sid
                                                           AND a.classid = 202202
                                          UNION ALL
                                          SELECT a.sid, a.name, a.classid, b.kemu, b.score
                                            FROM "student" a
                                            JOIN "score2" b ON a.sid = b.sid
                                                           AND a.classid = 202202) t202202 where t202201.kemu = t202202.kemu AND t202201.score NOT IN(SELECT score
                                                                    from score2
                                                                   where score2.kemu = t202201.kemu);

--3,查询班级202201语文成绩最高的学生,要求先创建索引,并且能保证一定会使用索引
oracle=> create index idx_sid_classid on student(sid,classid);
CREATE INDEX
oracle=> create index idx_kemu on score1(kemu);
CREATE INDEX
oracle=> create index idx_kemu2 on score2(kemu);
CREATE INDEX


EXPLAIN ANALYSE
SELECT max(score)
  FROM (SELECT max(score) AS score
          FROM "score1" c
         WHERE sid IN(SELECT sid
                        FROM "student" s
                       WHERE s.sid = c.sid
                         and s.classid = 202201
                         AND c.kemu = '语文')
        UNION ALL
        SELECT max(score) AS score
          FROM "score2" c
         WHERE sid IN(SELECT sid
                        FROM "student" s
                       WHERE s.sid = c.sid
                         and s.classid = 202201
                         AND c.kemu = '语文'));
                                                                           QUERY PLAN                                                           
                 
------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=251.20..251.21 rows=1 width=8) (actual time=0.106..0.106 rows=1 loops=1)
   ->  Append  (cost=125.58..251.19 rows=2 width=4) (actual time=0.069..0.103 rows=2 loops=1)
         ->  Aggregate  (cost=125.58..125.59 rows=1 width=8) (actual time=0.068..0.068 rows=1 loops=1)
               ->  Seq Scan on score1 c  (cost=0.00..125.54 rows=15 width=4) (actual time=0.036..0.063 rows=3 loops=1)
                     Filter: (SubPlan 5)
                     Rows Removed by Filter: 27
                     SubPlan 5
                       ->  Result  (cost=0.00..8.27 rows=1 width=4) (actual time=0.039..0.039 rows=3 loops=30)
                             One-Time Filter: ((c.kemu)::text = '语文'::text)
                             ->  Index Only Scan using idx_sid_classid on student s  (cost=0.00..8.27 rows=1 width=4) (actual time=0.022..0.022 rows=3 loops=10)
                                   Index Cond: ((sid = c.sid) AND (classid = 202201))
                                   Heap Fetches: 3
         ->  Aggregate  (cost=125.58..125.59 rows=1 width=8) (actual time=0.032..0.032 rows=1 loops=1)
               ->  Seq Scan on score2 c  (cost=0.00..125.54 rows=15 width=4) (actual time=0.007..0.032 rows=3 loops=1)
                     Filter: (SubPlan 6)
                     Rows Removed by Filter: 27
                     SubPlan 6
                       ->  Result  (cost=0.00..8.27 rows=1 width=4) (actual time=0.014..0.014 rows=3 loops=30)
                             One-Time Filter: ((c.kemu)::text = '语文'::text)
                             ->  Index Only Scan using idx_sid_classid on student s  (cost=0.00..8.27 rows=1 width=4) (actual time=0.009..0.009 rows=3 loops=10)
                                   Index Cond: ((sid = c.sid) AND (classid = 202201))
                                   Heap Fetches: 3
 Total runtime: 0.338 ms
(23 rows)

--4,查询202201班级的学生的成绩比202202班级的学生最高成绩还要大的学生信息,给出的查询是使用的<(小于号),要求进行改写。
SELECT t01.kemu, t01.score as t01_score, t02.score as t02_score
  FROM (SELECT kemu, score
          FROM "student" a
          JOIN "score1" b ON a.sid = b.sid
                         AND a.classid = 202201 ) t01
  JOIN (SELECT DISTINCT kemu, score
          FROM (SELECT b.kemu, max(b.score) AS score
                  FROM "student" a
                  JOIN "score1" b ON a.sid = b.sid
                                 AND a.classid = 202202
                 GROUP BY b.kemu
                UNION ALL
                SELECT b.kemu, max(b.score) AS score
                  FROM "student" a
                  JOIN "score2" b ON a.sid = b.sid
                                 AND a.classid = 202202
                 GROUP BY b.kemu)) t02 ON t02.score < t01.score AND t01.kemu = t02.kemu;
 kemu | t01_score | t02_score 
------+-----------+-----------
 语文 |        99 |        94
 数学 |        98 |        96
 英语 |        97 |        92
 语文 |        97 |        94
(4 rows)
===================================================================================================================================================


/*3 数据库连接
1,使用sql查询全局最大连接数
2,创建用户,指定连接数
3,查询用户的连接数
4,修改用户的连接数
5,创建数据库,指定连接数
6,查询数据库的连接数
7,修改数据库的连接数

4 数据库和用户管理
1)通过sql查询数据库最大连接数
2)创建用户user1指定最大连接数,指定连接数为3
3)修改用户user1最大连接数为10
4)通过sql查询该用户最大连接数
5)创建数据库并指定最大连接数为10
6)修改最大连接数为20
7)通过sql查询该用户最大连接数
*/


--5 SQL开发
--student(student_id,math,pysical,art,music)
create table student(student_id int,math int,phy int,art int,music int);
insert into student values (1,88,66,81,91),(2,33,44,55,66),(3,22,33,45,43),(4,99,88,80,79),(5,99,98,97,99),(6,90,98,97,90);
--1)编写存储过程,输入学生id返回总成绩
oracle=> create or replace procedure pro_sumscore(id int) as
oracle$> declare
oracle$> vstudent_id int;
oracle$> sumscore int;
oracle$> begin
oracle$> select student_id,math+phy+art+music into vstudent_id,sumscore from student where student_id=id;
oracle$> raise info 'student_id为%的学生的总成绩为%',id,sumscore;
oracle$> end;
oracle$> /
CREATE PROCEDURE
oracle=> call pro_sumscore(1);
INFO:  student_id为1的学生的总成绩为326
 pro_sumscore 
--------------
 
(1 row)
--2)对学习math和pysical排名前二的学生,art加5分,求所有学生总成绩
UPDATE "student"
   SET art = art + 5
 WHERE student_id in(SELECT student_id
                       FROM "student"
                      ORDER BY math + phy DESC
                      LIMIT 2);

SELECT student_id, math + phy + art + music AS sum_score
  from "student";

SELECT *
  FROM "student"
 ORDER BY 1;
--3)art和music排名前二,同时math和pysical在前二名的学生信息
oracle=> SELECT *
oracle->   FROM student
oracle->  WHERE student_id IN(SELECT student_id
oracle(>                        FROM student
oracle(>                       ORDER BY math + phy DESC
oracle(>                       LIMIT 2)
oracle->    AND student_id IN(SELECT student_id
oracle(>                        FROM student
oracle(>                       ORDER BY art + music DESC
oracle(>                       LIMIT 2);
 student_id | math | phy | art | music 
------------+------+-----+-----+-------
          5 |   99 |  98 |  97 |    99
          6 |   90 |  98 |  97 |    90
(2 rows)
--触发器
--department表和teacher表
CREATE TABLE department (
     did integer,
     teid integer,
     level integer
 )
 WITH (orientation=row, compression=no);
CREATE TABLE teacher (
     teid integer,
     name character varying
 )
 WITH (orientation=row, compression=no);
insert into teacher values (101,'a'),(102,'b'),(103,'c');
insert into department values (1,101,1),(2,102,2),(3,103,3);
--1,写一个触发器,当试图从表department中更改字段教师级别的时候,提示:部门表的教师级别不允许更改
CREATE OR REPLACE FUNCTION func_tri_change()
RETURNS TRIGGER
AS $$
BEGIN
  IF NEW.LEVEL != OLD.LEVEL THEN
    RAISE EXCEPTION '部门表的教师级别不允许更改';
  END IF;
  RETURN NEW;
END; $$ LANGUAGE PLPGSQL;
CREATE TRIGGER tri_change BEFORE UPDATE OF LEVEL ON "department" FOR EACH ROW EXECUTE PROCEDURE func_tri_change();
--验证触发器:
openGauss=> UPDATE department SET LEVEL=2 WHERE did=1;
ERROR:  部门表的教师级别不允许更改
--2,让触发器失效,再尝试更改教师级别
oracle=> alter table department disable trigger tri_change;
ALTER TABLE
oracle=> UPDATE department SET LEVEL=2 WHERE did=1;
UPDATE 1
--3,重新让触发器生效,再尝试更改教师级别
oracle=> alter table department enable trigger tri_change;
ALTER TABLE
openGauss=> UPDATE department SET LEVEL=2 WHERE did=1;
ERROR:  部门表的教师级别不允许更改

--6 安全审计
--1)创建用户user1,密码'test@123'
oracle=> create user user1 identified by 'test@123';
CREATE ROLE
--2)给用户授予查看审计权限,同时可以创建审计策略
--auditadmin可以查看审计策略
oracle=> alter user user1 auditadmin;
ALTER ROLE
--poladmin可以创建审计策略
oracle=> alter user user1 poladmin;
ALTER ROLE
--3)切换至user1,创建审计策略adt1,对数据库执行create操作创建
oracle=> create audit policy adt1 privileges create;
CREATE AUDIT POLICY
--4)创建审计策略adt2,数据库执行select操作创建审计策略
oracle=> create audit policy adt2 access select;
CREATE AUDIT POLICY
--5)修改adt1,对IP地址为'10.20.30.40'进行审计
oracle=> alter audit policy adt1 modify (filter on ip ('10.20.30.40'));
ALTER AUDIT POLICY
--6)创建表tb1
oracle=> create table tb1(id int);
CREATE TABLE
--7)创建审计策略adt3,仅审计计记录用户root,在执行针对表tb1资源进行的select、insert、delete操作数据库创建审计策略
openGauss=> create resource label rl_tb1 add table(tb1);
CREATE RESOURCE LABEL
oracle=> create audit policy adt3 access select on label(rl_tb1),insert on label(rl_tb1),delete filter on roles(root);
ERROR:  role: [root] is invalid
oracle=> create audit policy adt3 access select on label(rl_tb1),insert on label(rl_tb1),delete filter on roles(omm);
CREATE AUDIT POLICY
--8)关闭adt1审计策略
oracle=> alter audit policy adt1 disable;
ALTER AUDIT POLICY
--9)删除以上创建的审计策略,级联删除用户user1
oracle=> drop audit policy adt1,adt2,adt3;
DROP AUDIT POLICY
oracle=> drop user user1 cascade;
DROP ROLE
--5、用SQL查找employ表中的所有数据,如果工资大于9000,则下调百分之10;如果小于5000 则增加百分之10
create  table employ 
(emp_no int primary key, 
 ename   varchar2(18),
 salary  int,
 deptno  int,
 jointime date );

insert into employ
values
  (1, 'a', 10000, 1, now()),
  (2, 'b', 3000, 2, now());
  
SELECT emp_no,
       ename,
       CASE
         WHEN salary > 9000 THEN
           salary * 0.9
         WHEN salary < 5000 THEN
           salary * 1.1
         ELSE
           salary
       END AS adjusted_salary,
       deptno,
       jointime
  FROM employ;


--权限访问控制: 给用户u1赋权只允许访问all_data表id=1的数据,修改上面的权限改为只允许u1访问all_data表id=1和id=2的数据(据说有人碰到类似这样的题了,行级访问控制,比产品文档的例题稍微复杂一点).
openGauss=> select * from all_data ;
 id | role  |    data    
----+-------+------------
  1 | alice | alice data
  2 | bob   | bob data
  3 | peter | peter data
(3 rows)

openGauss=> alter table all_data enable row level security;
ALTER TABLE
openGauss=> create row level security policy rlsp_role on all_data using(case when current_user='u1' then id=1 end);
CREATE ROW LEVEL SECURITY POLICY
openGauss=> \c - u1
Password for user u1: 
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "postgres" as user "u1".
openGauss=> select * from jack.all_data ;
 id | role  |    data    
----+-------+------------
  1 | alice | alice data
(1 row)

openGauss=> \c - jack
Password for user jack: 
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "postgres" as user "jack".
openGauss=> alter row level security policy rlsp_role on all_data using(case when current_user='u1' then id=1 or id=2 end);
ALTER ROW LEVEL SECURITY POLICY
openGauss=> \c - u1
Password for user u1: 
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "postgres" as user "u1".
openGauss=> select * from jack.all_data ;
 id | role  |    data    
----+-------+------------
  1 | alice | alice data
  2 | bob   | bob data
(2 rows)


--20231228实战没做出来的题:
--以下只是题目逻辑,非原题:
openGauss=> create table stu(id varchar,name varchar);
CREATE TABLE
openGauss=> insert into stu values ('0001','name1'),('0002','name2'),('0003','name3'),('0004','name4');
INSERT 0 4
openGauss=> select * from stu ;
  id  | name  
------+-------
 0001 | name1
 0002 | name2
 0003 | name3
 0004 | name4
(4 rows)
在opengauss中写一个函数,第一个值是要选择的id,第二个值是其他id要被替换成的值。比如当id=0001要查表时,其他id被替换成****,name列不变
  id  | name  
------+-------
 0001 | name1
 **** | name2
 **** | name3
 **** | name4

比如当id=0002要查表时,显示如下
  id  | name  
------+-------
 **** | name1
 0002 | name2
 **** | name3
 **** | name4
 
 
openGauss=> CREATE OR REPLACE FUNCTION mask_id(var1 text, var2 text)
openGauss-> returns setof stu
openGauss-> as $$
openGauss$> DECLARE
openGauss$>   r stu % ROWTYPE;
openGauss$> BEGIN
openGauss$>   FOR r IN select case
openGauss$>                     when id = var1 then
openGauss$>                       id
openGauss$>                     else
openGauss$>                       '****'
openGauss$>                   end as id,
openGauss$>                   name
openGauss$>              from stu LOOP
openGauss$>     RETURN next r;
openGauss$>   end LOOP;
openGauss$>   RETURN;
openGauss$> end; $$ LANGUAGE plpgsql;
CREATE FUNCTION
openGauss=> call mask_id('0001','****');
  id  | name  
------+-------
 0001 | name1
 **** | name2
 **** | name3
 **** | name4
(4 rows)

openGauss=> call mask_id('0002','****');
  id  | name  
------+-------
 **** | name1
 0002 | name2
 **** | name3
 **** | name4
(4 rows)


/*

使用存储过程的优点包括:(考试让写4个)

1. **提高性能**:存储过程在数据库服务器上进行编译和优化,可以减少网络通信开销,提高执行速度。
2. **重用性**:存储过程可以在多个应用程序中被调用,提高代码复用性,减少开发工作量。
3. **安全性**:存储过程可以对数据进行权限控制,只允许授权用户执行特定操作,提高数据安全性。
4. **简化复杂操作**:存储过程可以封装复杂的业务逻辑,简化应用程序的开发过程。
5. **减少数据传输**:存储过程可以返回结果集,减少了数据传输的量,提高了系统性能。
6. **良好的封装性**:在进行相对复杂的数据库操作时,原本需要使用一条一条的 SQL 语句,可能要连接多次数据库才能完成的操作,现在变成了一次存储过程,只需要连接一次即可。
7. **减少网络通信开销**:由于存储过程在数据库服务器上执行,因此可以减少客户端和服务器之间的网络通信开销。
8. **提高开发效率**:存储过程可以封装复杂的业务逻辑,使得开发人员可以专注于应用程序的开发,而不是数据库的操作。


存储过程和函数的区别如下:(考试让写3个)

1. **定义**:存储过程是SQL语句和可控制流程语句的预编译集合,以一个名称存储并作为一个单元处理。函数则是由一个或多个SQL语句组成的子程序,可用于封装代码以便重新使用。
2. **参数**:存储过程可以返回参数,如记录集,函数只能返回值或者表对象。存储过程的参数有in,out,inout三种,存储过程声明时不需要返回类型。而函数参数只有in,函数需要描述返回类型,且函数中必须包含一个有效的return语句。
3. **使用条件**:存储过程可以在单个存储过程中执行一系列SQL语句,而且可以从自己的存储过程内引用其他存储过程,这可以简化一系列复杂语句。而函数有许多限制,如不能使用临时表,只能使用表变量等。
4. **执行方式**:存储过程可以返回参数,如记录集,函数只能返回值或者表对象。
5. **功能**:存储过程可以用于执行一组修改全局数据库状态的操作。而函数则不能用于此类操作。
6. **性能**:由于存储过程是预编译的,因此其执行速度通常比函数快。


存储过程和匿名块的区别如下:(考试让写2个)
1. **定义**:存储过程是命名的SQL语句集合,可重复使用,不需声明变量。匿名块则是未命名的代码块,每次执行时都需要重新编写或粘贴。
2. **使用方式**:存储过程可以通过调用其名称来执行,无需每次都重新编写SQL语句。而匿名块则需要每次执行时重新编写或粘贴。
3. **重复使用性**:存储过程可以重复使用,减少代码的重复编写。而匿名块则无法重复使用。
4. **代码组织结构**:存储过程可以组织成模块化的结构,使得代码更加清晰和易于维护。而匿名块则没有这样的组织结构。


1、全量备份、差分备份和增量备份区别
全量备份是对数据库当前所有数据的整体备份,备份集一般较大,恢复时间较长。
差分备份是基于上一次全量备份之后的差异数据的备份,备份集一般比全量小,恢复时候要先恢复全量再恢复差异部分。
增量备份基于的是上一次增量,所以恢复时可能要恢复全量+多次增量备份。

2、全量备份、差分备份、增量备份集大小关系
一般情况下是全量>差分>增量

3、数据可以恢复到指定时间点,使用什么技术实现,与物理文件备份相比,这种依赖哪个关键文件。
使用的是PITR技术,主要依赖的是WAL日志文件。


1,数据库事务什么?GaussDB(for opengauss)如何管理事务?
数据库事务是一组具有ACID特性的能访问数据库内部对象的可执行序列。
OpenGauss这样开启并结束事务
oracle=> start transaction isolation level serializable read write;
START TRANSACTION
oracle=> end;
COMMIT
oracle=> start transaction isolation level READ COMMITTED READ WRITE;
START TRANSACTION
oracle=> end;
COMMIT
oracle=> start transaction isolation level repeatable READ READ WRITE;
START TRANSACTION
oracle=> end;
COMMIT


2,GaussDB(for opengauss)支持哪些事务隔离级别,每种如何理解?
三种隔离级别,分别是
read commited 读已提交:就是A窗口可以读到B窗口已提交的数据,未提交的无法读到。
repeatable read 可重复读:就是A窗口无法读到B窗口已提交的数据,事务开始时会生成读视图贯穿整个事务。
SERIALIZABLE 可串行化:事务只能串行执行,降低数据库效率,一般不采用。


3,使用命令启动一个事务,并且设置事务类型为只读
oracle=> start transaction isolation level repeatable read read only;
START TRANSACTION
oracle=> end;
COMMIT


RBAC和ABAC是两种不同的权限管理模型,它们的主要区别体现在以下几个方面:

1. 权限授予方式:RBAC是基于角色进行权限授予,即根据角色赋予权限。而ABAC则是基于属性进行权限授予,即根据用户、环境或资源的属性来决定是否赋予权限。
2. 灵活性:RBAC的模型构建相对简单,对于中小型组织来说,维护角色和授权关系的工作量不大,反而定制各种策略相对麻烦。而ABAC则更加灵活,可以根据用户特征、对象特征、操作类型等属性确定访问权限,适用于大型组织。
3. 粒度:RBAC控制整个组织的广泛访问,而ABAC则采用细粒度方法。这意味着在考虑RBAC与ABAC时,RBAC控制整个组织的广泛访问,而ABAC则采用细粒度方法。

ACL:访问控制列表


RBAC:基于角色的访问控制,角色通常是指具有某些共同特征的一组人,例如:部门、地点、资历、级别、工作职责等。
在系统初始时Admin根据业务需要创建多个拥有不同权限组合的不同角色,当需要赋予某个用户权限的时候,把用户归到相应角色里即可赋予符合需要的权限。

ABAC:基于属性的访问控制,这包括用户属性、环境属性和资源属性。
用户属性:包括如用户的姓名、角色、组织、ID和安全许可等内容
环境属性:包括如访问时间、数据的位置和当前组织的威胁等级。
资源属性:包括如创建日期、资源所有者、文件名和数据敏感性。

两者区别:
RBAC与ABAC之间的主要区别在于方法授予访问权限的方式。 RBAC按照角色授予访问权限,ABAC可以根据用户特征,对象特征,操作类型等属性确定访问权限。

ACL:访问控制列表


数据库数据加密方式有哪些,至少3种
对称加密 AES
非对称加密 DES
透明加密 TDE
行级访问控制
数据脱敏
*/

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。