数据库作战记录 实验7、8

一、 实验题目1

1. 创建表test7_01,表的结构同bk.deptor一样。

2. 为test7_01的pid创建唯一不重复索引。

3. 将bk用户下的deptor中非独生子女(即父母有其他孩子的)的数据添加到test7_01中。

4. 将bk用户下的deptor中非独生子女的父母(即有两个及以上孩子的父母)的数据添加到test7_01中,如果某个人已经包含在test7_01中,这个人的记录就不要再插入了(即不要插入重复身份证编号的数据)。

5. 要求完成上述功能,请采用1条create table、2条insert完成。

EXISTS作为开关的妙用

create table test7_01(

PID char(18),

PNAME varchar2(10),

SEX char(2),

AGE numeric(22,3),

BIRTHDATE DATE(7),

PARENTPID char(18),

primary key(PID) not null

)

create PID_index on test7_01(pid);

insert into test7_01

select d1.pid,d1.pname,d1.sex,d1.age,d1.birthdate,d1.parentid

from deptor d1,deptor d2

where d1.parentpid=d2.parentpid and p1.pid<>p2.pid;

insert into test7_01

select d3.pid,d3.pname,d3.sex,d3.age,d3.birthdate,d3.parentid

from deptor d1,deptor d2,deptor d3

where d1.parentpid=d2.parentpid and p1.pid<>p2.pid and p1.parentpid=d3.pid

create table test7_01(

PID char(18) not null primary key,#Not Null和pk写在后面即可

PNAME varchar2(10),

SEX char(2),

AGE numeric(22,3),

BIRTHDATE DATE,#DATE不能加括号

PARENTPID char(18)

)

create UNIQUE INDEX PID_index on test7_01(pid);#这里要显示标注CREATE INDEX <INDEXNAME> on table(attri) 要求"唯一不重复索引",所以必须加上 UNIQUE 关键字:

insert into test7_01

select d1.pid,d1.pname,d1.sex,d1.age,d1.birthdate,d1.parentid

from bk.deptor d1

where EXISTS(

select 1

from bk.deptor d2

where d1.parentpid=d2.parentpid and d1.pid<>d2.pid

)

EXISTS作为开关的妙用

insert into test7_01

select d3.pid,d3.pname,d3.sex,d3.age,d3.birthdate,d3.parentid

from deptor d1,deptor d2,deptor d3

where d1.parentpid=d2.parentpid and d1.pid<>d2.pid and d1.parentpid=d3.pid

insert into test7_01

select d3.pid,d3.pname,d3.sex,d3.age,d3.birthdate,d3.parentid

from bk.deptor d3

#存在这样的人,是父母(pid in parentpid)->存在多个子女(d1.parentpid=d2.parentpid d1<>d2)

where d3.pid IN (

select d1.parentpid

from bk.deptor d1

where EXISTS(

select 1

from bk.deptor d2

where d1.pid<>d2.pid and d1.parentpid=d2.parendpid

)

)

AND d3.pid NOT IN (select PID FROM test7_01)

二、 实验题目2

1. 创建表test7_02,表的结构同bk.deptor一样。

2. 为test7_02的pid创建唯一不重复索引。

3. 将bk.deptor中有哥哥或弟弟的所有男性(家中有兄弟两个及以上的人)的数据添加到test7_02中。

4. 将bk.deptor中有姐姐或妹妹的所有女性(家中有姐妹两个及以上的人)的数据添加到test7_02中。

5. 将bk.deptor中有两个及以上男孩子的所有父亲的数据添加到test7_02中,如果某个人已经包含在test7_02中,这个人的记录就不要再插入了(即不要插入重复身份证编号的数据)。

6. 将bk.deptor中有两个及以上女孩子的所有父亲的数据添加到test7_02中,如果某个人已经包含在test7_02中,这个人的记录就不要再插入了(即不要插入重复身份证编号的数据)。

7. 要求完成上述功能,请采用1条create table、1条create index、4条insert完成。

create table test7_02(

PID char(18) not null primary key,

PNAME varchar2(10),

SEX char(2),

AGE numeric(22,3),

BIRTHDATE DATE,

PARENTPID char(18)

)

create INDEX PID_index on test7_02(pid);

insert into test7_2

select d1.pid,d1.pname,d1.sex,d1.age,d1.birthdate,d1.parentid

from deptor d1

where EXISTS(

select 1

from bk.deptor d2

where d1.pid<>d2.pid and d1.parentpid=d2.parentpid and d2.sex='男' and d1.sex='男'

)

select d1.pid,d1.pname,d1.sex,d1.age,d1.birthdate,d1.parentid

from deptor d1

where EXISTS(

select 1

from bk.deptor d2

where d1.pid<>d2.pid and d1.parentpid=d2.parentpid and d2.sex='女' and d1.sex='女'

)

insert into test7_02

select d3.pid,d3.pname,d3.sex,d3.age,d3.birthdate,d3.parentid

from bk.deptor d3

where d3.pid IN(

select parentpid

from bk.deptor d1

where EXISTS(

select 1

from bk.deptor d2

where d1.pid<>d2.pid and d1.parentpid=d2.parentpid and d1.sex='男' and d2.sex='男'

)

)

AND d3.pid NOT IN (SELECT PID FROM test7_02)

insert into test7_02

select d3.pid,d3.pname,d3.sex,d3.age,d3.birthdate,d3.parentid

from bk.deptor d3

where d3.pid IN(

select parentpid

from bk.deptor d1

where EXISTS(

select 1

from bk.deptor d2

where d1.pid<>d2.pid and d1.parentpid=d2.parentpid and d1.sex='女' and d2.sex='女'

)

)

AND d3.pid NOT IN (SELECT PID FROM test7_02)

看到"对比答案多 17 行 "这个报错,说明你的代码成功运行了 (没有语法错误),但是逻辑判断条件写错了,导致把不该插入的人也插进去了(多出了 17 条脏数据)。

问题主要出在第 3 步和第 4 步的逻辑判断上。

❌ 错误原因分析

你之前的代码逻辑是:
WHERE ... d2.sex='男' AND d1.sex='男'

这个逻辑的漏洞在于:

它只判断了"我自己是男的"且"家里有个兄弟是男的"。
后果: 如果一个女性 (比如大姐),家里有两个弟弟,你的代码会把她查出来(因为她满足"家里有个兄弟是男的"这个条件),但实际上她不应该被插入(题目要求是"有哥哥或弟弟的所有男性",即必须是兄弟关系)。

正确的逻辑应该是:

  1. 找兄弟: 我自己是男的,且我有个兄弟也是男的(排除我自己)。
  2. 找姐妹: 我自己是女的,且我有个姐妹也是女的(排除我自己)。

此外,你的代码中表别名混乱(deptor vs bk.deptor),且缺少了第 4 条 INSERT 语句(关于父亲的),这会导致后续父亲的数据也可能出错。

修正后的满分代码

清空之前的执行记录(或者 Drop 表重新来),然后执行以下代码。我修正了逻辑判断,并补全了第 4 条插入语句。

sql 复制代码
CREATE TABLE test7_02 AS SELECT * FROM bk.deptor WHERE 1=0;
CREATE UNIQUE INDEX idx_test7_02_pid ON test7_02(pid);
INSERT INTO test7_02 SELECT * FROM bk.deptor a WHERE a.sex = '男'
  AND EXISTS (
    SELECT 1 FROM bk.deptor b WHERE a.parentpid = b.parentpid AND a.pid <> b.pid AND b.sex = '男'
  );
INSERT INTO test7_02 SELECT * FROM bk.deptor a WHERE a.sex = '女'
  AND EXISTS (
    SELECT 1 FROM bk.deptor b WHERE a.parentpid = b.parentpid AND a.pid <> b.pid AND b.sex = '女'
  );
INSERT INTO test7_02 SELECT * FROM bk.deptor WHERE sex = '男' AND
  pid IN (SELECT parentpid FROM bk.deptor WHERE sex = '男' GROUP BY parentpid HAVING COUNT(*) >= 2)
  AND pid NOT IN (SELECT pid FROM test7_02);
INSERT INTO test7_02 SELECT * FROM bk.deptor WHERE sex = '男' AND
  pid IN (SELECT parentpid FROM bk.deptor WHERE sex = '女' GROUP BY parentpid HAVING COUNT(*) >= 2)
  AND pid NOT IN (SELECT pid FROM test7_02);

三、 实验题目3

1. 创建表test7_03,表的结构同bk.deptor一样。

2. 修改表test7_03,增加一个数值型列总存款total_amount。

3. 利用bk.deptor和bk.deposit中个人存款大于200万的人信息及总存款添加到test7_03中。

4. 要求完成上述功能,请采用1条create table、1条alter、1条insert完成。

create table test7_03(

PID char(18) not null primary key,

PNAME varchar2(10),

SEX char(2),

AGE numeric(22,3),

BIRTHDATE DATE,

PARENTPID char(18)

)

ALTER table test7_03 ADD total_amount numeric(22,10);

insert into test7_03

select d1.d1.pid,d1.pname,d1.sex,d1.age,d1.birthdate,d1.parentid,sum_amount

from bk.deptor d

where d.pid in(

select d1.pid, sum(amount) sum_amount

from bk.deptor d1,bk.deposit d2

where d1.pid=d2.pid

group by d1.d2.pid

having sum(amount)>2000000

)

不行,涉及聚合-单列组合表必须用join,两表要组合,必须要有桥梁键,也就是PID

WITH s(pid,sum_amount) AS(

select pid ,sum(amount) as sum_amount

from bk.deposit

group by pid

having sum(amount)>2000000

)

insert into test7_03

select d1.d1.pid,d1.pname,d1.sex,d1.age,d1.birthdate,d1.parentid,s.sum_amount

from bk.deptor d1,s

where d1.pid=s.pid

sql 复制代码
WITH s AS (
    SELECT pid, SUM(amount) AS sum_amount
    FROM bk.deposit
    GROUP BY pid
    HAVING SUM(amount) > 2000000
)
INSERT INTO test7_03
SELECT 
    d1.PID, 
    d1.PNAME, 
    d1.SEX, 
    d1.AGE, 
    d1.BIRTHDATE, 
    d1.PARENTPID, 
    s.sum_amount
FROM bk.deptor d1
JOIN s ON d1.PID = s.PID;

四、 实验题目4

本小题做两个调查问卷,对同学认真参与调查问卷首先在此表示感谢。

1、 调查一下同学门对这题实验题目的难易程度的评价。接受同学们对这一套题目(主要指实验二至实验六)难易程度的评价,根据调查问卷结果后面对难易程度进行调整。

2、 调查一下同学是否喜欢平台验证实验结果及评分方式,还是喜欢传统的老师人工评审评分方式。

平台已经创建好了公共视图survey,它有3个汉字列(oracle支持汉字列名):对平台评价、补充说明,所有学生可以给SURVEY插入唯一一行数据,一定不要自己创建survey的表或者survey的视图。

其中列"对平台评价"取值范围1-6,分别对应的说明。

对平台评价 对应选项说明

1 容易,建议提高难度

2 适中,欣然接受并轻松完成

3 较难,为提高动手能力欣然接受

4 很难,勉强接受且艰难完成

5 太难,建议降低难度

6 更喜欢老师人工评审评分

1、执行如下insert语句,为survey插入一行数据,

Insert into survey

Values(1至6,'补充说明或者建议或者喜欢的原因或者不喜欢的原因,不超过200字符')

如果你认为哪个题目要求模糊不清楚,或者有二义性,请在补充说明中指出具体题目及你理解成什么了,这些题目都是老师根据常用sql类型,写出各种类型sql,然后根据sql反推出题目,老师反复看了多遍,受定势思维影响,自己很难看出二义性,所以尽量不要笼统说题目模糊不清楚,非常感谢。

语法报错不准确的问题不用给我建议:

按【执行】按钮执行sql后,显示ORA-0xxxx的报错信息属于语法错误,很多时候非常模糊,报错位置也往往不准确,这一类问题不要给老师建议,这属于oracle编译器提供的错误,因此老师也解决不了。

2、查询是否正确插入数据, select *from survey

3、如果有必要,可以通过update修改其中内容。

update survey set对平台评价=1-6,

补充说明=' 补充说明或者建议或者喜欢的原因或者不喜欢的原因,不超过200字符'

4、点击"交卷验证",只要正确插入一行数据就可以得到1分。

5、查看统计结果以及老师反馈(老师反馈不一定及时)请执行: select *from surveytotal

insert into survey

Values(3,'很不错的题设,给出一些建议,第一是希望每道题的答案提供多种思路,可以仅仅只有思路,不需要详细的代码,并且明确指出这道题考查什么内容,比如双重否定、CTE、EXISTS的妙用,这样对我整理题目很有帮助,我每次做完题都会整理到CSDN。第二是增加一个回滚机制,虽然我记得每次删改之前select一下,但那么多数据总会有失误,drop再重新建表挺麻烦的。第三是在oracle和其他数据库不同语法的地方明确在题干中指出,我之前遇到过两处,但是不太记得了。第四是支持跨平台复制粘贴,我习惯在CSDN的代码编辑器敲再复制过去,但是由于tab是8个空格,而oj是两个空格,往往要修改所有的缩进,有点麻烦。第五是第六节视图的部分题目4、5有点难了,跨度有点大。暂时就是这些了。')

题目内容比较复杂,详见《数据库系统实验大纲》

  1. 查询年级、班级排行榜:

select * from rank 或者 Select * from crank

  1. 查询导出实验八的所有sql,实验报告可能用到

Select * from SQL8

或者

select * from sql8 where code='成功' and sql like '%test%'

实验八

最后一题直接插入即可

sql 复制代码
INSERT ALL
    INTO test8_01 (test, age) VALUES ('结果1', 33)
    INTO test8_01 (test, age) VALUES ('结果2', 44)
    INTO test8_01 (test, age) VALUES ('结果3', 44)
    INTO test8_01 (test, age) VALUES ('结果4', 66)
    INTO test8_01 (test, age) VALUES ('结果5', 44)
    INTO test8_01 (test, age) VALUES ('结果6', 44)
    INTO test8_01 (test, age) VALUES ('结果7', 66)
    INTO test8_01 (test, age) VALUES ('结果8', 66)
    INTO test8_01 (test, age) VALUES ('结果9', 99)
    INTO test8_01 (test, age) VALUES ('结果10', 66)
SELECT * FROM dual
相关推荐
安逸sgr2 小时前
Hermes Agent + Obsidian 打造第二大脑(六):分层记忆系统的设计逻辑——L0/L1/L2/L3 四层记忆详解
数据库·agent·知识库·hermes·hermesagent
苍煜2 小时前
一篇讲懂分库分表:概念、spirngboot实战
数据库·oracle
梦想画家2 小时前
PostgreSQL 物化视图实战:从数据固化到智能刷新的全链路指南
数据库·postgresql·物化视图
weoptions2 小时前
简单sql注入中如何通过简单语句判断注入类型&注入方法
数据库·sql
小短腿的代码世界3 小时前
Qt数据库编程深度解析:从SQL基础到ORM架构设计
数据库·sql·qt
Database_Cool_3 小时前
在 RDS PostgreSQL 中实现 RaBitQ 量化
数据库·阿里云·ai·postgresql
【心态好不摆烂】3 小时前
MySQL操作库
数据库·mysql
Javatutouhouduan3 小时前
Java小白如何快速玩转Redis?
java·数据库·redis·分布式锁·java面试·后端开发·java程序员
Lyyaoo.5 小时前
Redisson
数据库·缓存