这里我们建几个SQL表,我们用个图来说明关系这里tid的值和教师表中的id相匹配,pid和院系表中的id相匹配,也就是说这样建表就把三张表的关系给建立起来了。
学生表在最低层,院系表在最高层。
而这里我们就要讲一个外键的概念:外键是作为与主表的主键相关联的键值,外键可以有多个,同时有外键的表称作对应主键所在表的从表,那主键所在的表就作主表。
图中,tid 是教师表中id的外键,也就学生表是教师表的从表,同理,教师表也就是院系表的从表。
外键的主要作用是保持数据一致性,完整性,主要目的是控制存储在外键表中的数据。
当然在这时我们还不需要去建立真正的外键联系关系现在我们要查询学生表,教师表,院系表的所有信息:select * from student,teacher,part //查询这三个表中的所有信息我们现在要查询某学生的教师是的名字:select teaname from student,teacher where (student.id ='') and (teacher.id = student.tid)//这里有两个约束条件,一个是约束学生的id号,一个是约束学生表和教师表的数据要相对应,也就是,这样查询的结果,就是该学生tid所对应教师表中id号的teaname字段的数据,也就是这位学生的教师名字了现在有一个问题,我想问这个学生所在院系是什么?这个问题就应该迎刃而解了吧。
当然这只是简单的多表查询,其实在真正多表查询时,是用的以下方法:这里讲一个join方法该语句是实现多对对查询或一对一查询的方法,当我们在用简单多表查询的时候,它的匹配是无逻辑的,也就是没有具体的约束条件,它不会按照逻辑关系来约束。
有可能这个学生会和一个无关第教师联系起来,或者和一个无关的院系联系起来。
我们用一个简单的join方法查询:select teacher.teaname from student join teacher on(student.tid = teacher.id)where (student.id='1') //查询id号为1的学生的教师的名字这就是join语句的语法,它是个嵌套语句,也就是把一个表嵌套在另一个表中,一般都是自下而上的嵌套,如上例,就是学生表去加入教师表的集合。
也就是从表加入主表。
这种join有两个参数,我们上例用的是缺省参数--innor,当我们直接用join时,就默认是这个参数,还有一个left,这两个参数在用时有很大的区别。
select * from student left join teacher on(student.tid = teacher.id)这上面这个例子中,用left和不用left参数是有很大区别的。
用如果在学生表中,有几个新报道的学生还未分配教师,那么,用left参数查询的时候也会显示出来,尽管他的tid为空,和教师表中的数据不匹配,但也会显示出来。
若不用left ,那么就不会显示这几个新学生。
通过这个例子应该能更好的理解left的用处了吧,在处理中,我们要根据需求来进行设计查询语句。
当然,我们先前讲的外键这个时候我们也需要拿出来用了。
下图所示:我们现在建好了这个表,我们有如下设计需求,当我在删掉这个类别的时候,我们需要把该类别下的产品也删掉。
我们可以用最原始的方法,也就是先查询所有该类别的产品,然后把类别下的产品全删完后才删除该类别,但这样,不显得很麻烦吗?这里就该用上外键的功能了,首先我们建立好外键,也就是把cid设为类别表中id的外键 ALTER TABLE product ADD CONSTRAINT fk_product_cidFOREIGN KEY (cid)REFERENCES category(id);//第一行是在product(产品表)中添加一个外键,第二行是此外键对应的字段是cid,第三行是此外键对应的键值为category(类别表)中的id.那么这就建立好了外键的关系,但是这样还是不行,我们还需要了解一下外键的级联操作的相关信息:CASCADE(连锁关系,当主表变更,从表的相应信息也会变更)RESTRICT(禁止主表变更)SET NULL(子表相应字段设置为空)。
一般我们用的最多的是连锁关系,而上例所讲的设计我们就需要用到连锁关系:ALTER TABLE product ADD CONSTRAINT fk_product_cidFOREIGN KEY (cid)REFERENCES category(id);ON UPDATE CASCADE;ON DELETE CASCADE;//这就实现了更新的连锁和删除的连锁。
也就是当主表的信息变更,从表的相关信息也会变更。
当主表的信息删除,从表的相关联信息也会删除--------------------------------------------------------------------------------------------------------------------------------------------问题及描述:--1.学生表Student(S#,Sname,Sage,Ssex) --S# 学生编号,Sname 学生姓名,Sage 出生年月,Ssex学生性别--2.课程表Course(C#,Cname,T#) --C# --课程编号,Cname 课程名称,T# 教师编号--3.教师表Teacher(T#,Tname) --T# 教师编号,Tname 教师姓名--4.成绩表SC(S#,C#,score) --S# 学生编号,C# 课程编号,score 分数*/--创建测试数据create table Student(S# varchar(10),Sname nvarchar(10),Sage datetime,Ssex nvarchar( 10))insert into Student values('01' , N'赵雷' , '1990-01-01' , N'男')insert into Student values('02' , N'钱电' , '1990-12-21' , N'男')insert into Student values('03' , N'孙风' , '1990-05-20' , N'男')insert into Student values('04' , N'李云' , '1990-08-06' , N'男')insert into Student values('05' , N'周梅' , '1991-12-01' , N'女')insert into Student values('06' , N'吴兰' , '1992-03-01' , N'女')insert into Student values('07' , N'郑竹' , '1989-07-01' , N'女')insert into Student values('08' , N'王菊' , '1990-01-20' , N'女')create table Course(C# varchar(10),Cname nvarchar(10),T# varchar(10))insert into Course values('01' , N'语文' , '02')insert into Course values('02' , N'数学' , '01')insert into Course values('03' , N'英语' , '03')create table Teacher(T# varchar(10),Tname nvarchar(10))insert into Teacher values('01' , N'张三')insert into Teacher values('02' , N'李四')insert into Teacher values('03' , N'王五')create table SC(S# varchar(10),C# varchar(10),score decimal(18,1))insert into SC values('01' , '01' , 80)insert into SC values('01' , '02' , 90)insert into SC values('01' , '03' , 99)insert into SC values('02' , '01' , 70)insert into SC values('02' , '02' , 60)insert into SC values('02' , '03' , 80)insert into SC values('03' , '01' , 80)insert into SC values('03' , '02' , 80)insert into SC values('03' , '03' , 80)insert into SC values('04' , '01' , 50)insert into SC values('04' , '02' , 30)insert into SC values('04' , '03' , 20)insert into SC values('05' , '01' , 76)insert into SC values('05' , '02' , 87)insert into SC values('06' , '01' , 31)insert into SC values('06' , '03' , 34)insert into SC values('07' , '02' , 89)insert into SC values('07' , '03' , 98)go--1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数--1.1、查询同时存在"01"课程和"02"课程的情况select a.* , b.score [课程'01'的分数],c.score [课程'02'的分数]from Student a , SC b , SC c where a.S# = b.S# and a.S# = c.S# and b.C# ='01'and c.C# ='02'and b.score > c.score --1.2、查询同时存在"01"课程和"02"课程的情况和存在"01"课程但可能不存在"02"课程的情况(不存在时显示为null)(以下存在相同内容时不再解释)select a.* , b.score [课程"01"的分数],c.score [课程"02"的分数]from Student aleft join SC b on a.S# = b.S# and b.C# ='01'left join SC c on a.S# = c.S# and c.C# ='02'where b.score >isnull(c.score,0)--2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数--2.1、查询同时存在"01"课程和"02"课程的情况select a.* , b.score [课程'01'的分数],c.score [课程'02'的分数]from Student a , SC b , SC c where a.S# = b.S# and a.S# = c.S# and b.C# ='01'and c.C# ='02'and b.score < c.score --2.2、查询同时存在"01"课程和"02"课程的情况和不存在"01"课程但存在"02"课程的情况select a.* , b.score [课程"01"的分数],c.score [课程"02"的分数]from Student aleft join SC b on a.S# = b.S# and b.C# ='01'left join SC c on a.S# = c.S# and c.C# ='02'where isnull(b.score,0) < c.score--3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩select a.S# , a.Sname , cast(avg(b.score) as decimal(18,2)) avg_scorefrom Student a , sc bwhere a.S# = b.S#group by a.S# , a.Snamehaving cast(avg(b.score) as decimal(18,2)) >=60order by a.S#--4、查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩--4.1、查询在sc表存在成绩的学生信息的SQL语句。