一、 实验题目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='男'
这个逻辑的漏洞在于:
它只判断了"我自己是男的"且"家里有个兄弟是男的"。
后果: 如果一个女性 (比如大姐),家里有两个弟弟,你的代码会把她查出来(因为她满足"家里有个兄弟是男的"这个条件),但实际上她不应该被插入(题目要求是"有哥哥或弟弟的所有男性",即必须是兄弟关系)。
正确的逻辑应该是:
- 找兄弟: 我自己是男的,且我有个兄弟也是男的(排除我自己)。
- 找姐妹: 我自己是女的,且我有个姐妹也是女的(排除我自己)。
此外,你的代码中表别名混乱(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有点难了,跨度有点大。暂时就是这些了。')
题目内容比较复杂,详见《数据库系统实验大纲》
- 查询年级、班级排行榜:
select * from rank 或者 Select * from crank
- 查询导出实验八的所有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