实训时光---数据库基础知识

/*1. 可利用的资源*/
-- 帮助手册
-- AdventureWorks


-- 创建数据库
-- create database StudentManager


-- 如何学习创建数据库 点击一个已经创建好的数据库,右键 编写数据库脚本 到 新建查询,就会出现编写数据库的脚本。
/*
CREATE DATABASE [StudentManager] ON  PRIMARY 
( NAME = N'StudentManager', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\StudentManager.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
 LOG ON 
( NAME = N'StudentManager_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\StudentManager_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
 COLLATE Chinese_PRC_CI_AS
GO
*/


--删除数据库
--DROP DATABASE [Student Manager]


/*
如何设计数据库表
学生管理系统,学生信息(编号,姓名,性别,出生日期),课程信息(课程编号,课程名称),学生可以选择课程,
我们可以给学生一个分数。
*/


/*
概念萃取
名词和动词
名词:学生信息(编号,姓名,性别,出生日期) , 课程信息(课程编号,课程名称)
动词:选择课程(选课)分数
*/


/*
绘制ER图


矩形===》实体
椭圆===》属性
菱形===》关系


元:关系链接实体的个数 一元关系,二元关系,多元关系
映射基础:m:n  
*/




/*
转换成表


1. 如果是m:n的关系,实体转换成表,关系也转换成一张表,并且将两端实体的主键拿过来做关系的外键,同时构成该表的复合主键.
2. 如果是1:n的关系,实体转换成表,关系不转换成表,我们将1端实体的主键,拿过来过N端实体外键
3. 如果是1:1的关系,实体转换成表,关系不转换成表,我们将任意一端实体的主键,作为另外一端实体的外键


*/


/*
课堂作业:
旅游公司 可以组团进行旅游(公司编号,组织机构代码,公司名字)
1个导游(导游编号,导游姓名)可以导很多条路线(路线编号,路线),一个路线可以被很多导游导。
一个导游可以从属于N个旅游公司。导游的线路属于某一个公司,一个公司有多条线路。


名词:旅游公司 , 导游 , 路线 
动词:公司管理导游  导游导路线
*/


/*
范式:第一范式(课后思考),第二范式,第三范式
第二范式:不存在局部依赖
第三范式:不存在传递依赖


A决定B,我就说B依赖于A


第三范式:
学生信息(编号,姓名,性别,出生日期,班级编号,班级名称)
    1001 张三丰 男 1919-5-4 1 一班
1002 张四丰 男 1919-5-5 1 二班


修改如下:
编号,姓名,性别,出生日期,班级编号
班级编号,班级名称


1001 张三丰 男 1919-5-4 1 
1002 张四丰 男 1919-5-5 1 


1  二班


课下作业:第一范式的准确概念
*/


/***********************第二天****************************/
/*
1. 数据类型
F1 ---> 输入数据类型
1.1 精确数字
int 4字节32位    -2的(32-1)的次方 ~ 2的(32-1)的次方-1
decimal 小数  numeric(p [, s])   numeric(4)或者numeric(4,3)
numeric(4,1) ==> 999.9    
tinyint [0-255]
bit : 0 , 1 ==> 如果我向里面存储一个2, 不会报错,存储进去是1 ,非0即真




import :  int  numeric  bit
1.2 日期类型
datetime 1753年开始的


1.3 字符串
char和varchar的区别: 
char:定长
varchar:可变长度

name char(8)  张三 : 并不是占了4个字节,而是固定长度8个字节  最多8000个字节
name varchar(8) 张三: 他占4个字节 


text : 取值范围特别大,最大长度为 2^31-1 (2,147,483,647) 个字符


char和nchar区别:
name char(4) : 张三丰 
name nchar(4) : ABCDF   unicode编码的


1.4 二进制
密码   文件  图像存储


1.5 uniqueidentifier类型
可以作为表的主键,但是,他只能做小表(表比较小,数据比较少),如果是大型的表或者数据比较多的情况下,速度慢。


*/


/*
创建表
*/
create table S
(
SID int ,
SName varchar(10),
SSex char(2),
SBirthday datetime,
SAddress nvarchar(100),
SStatus bit
)
GO


insert into S values( 1001 , '张三丰' , '男' , '1989-01-01' , '五台山' , 1 )
select * from S
-- 删除表
drop table S


/*
约束种类
一、主键约束
二、不能为空约束
三、检查约束
*/
create table S
(
SID int primary key ,    -- PK 主键
SName varchar(10) not null,  -- 不能为空约束
SSex char(2) check ( SSex  in ( '男' , '女' ) ) ,  -- 必须存储 男或者女        检查约束
SBirthday datetime, 
SAddress nvarchar(100),
SStatus bit
)
GO




insert into S values( 1001 , '张三丰' , '男' , '1989-01-01' , '五台山' , 1 )
insert into S values( 1002 , '杨玉环' , '女' , '1989-01-01' , '感恩寺' , 1 )


/*
四、唯一约束
*/
create table C
(
CID int identity(1,1) primary key,
CName varchar(100) unique
)


insert into C values('高等数学')
insert into C values('数据结构')


select * from C
/*
PK(SID,CID)
五、唯一约束
*/
create table SC
(
SID int , 
CID int ,
Score numeric( 4,1 ) check (Score >=0 and Score <= 100 ) ,  -- 0 , 100 , 99.5
primary key ( SID , CID ),
foreign key (SID) references S(SID),
foreign key (CID) references C(CID)
)


insert into SC values(1001 , 1 , 100)
insert into SC values(1001 , 2 , 90)
insert into SC values(1002 , 2 , 10)


-- DDL(create,drop,alter and so on) 和 DML(update,insert,delete and so on)语句 
/*
约束的标准语法
*/
create table S
(
SID int not null,    -- PK 主键
SName varchar(10) not null,  -- 不能为空约束
SSex char(2)  ,  -- 必须存储 男或者女        检查约束
SBirthday datetime, 
SAddress nvarchar(100),
SStatus bit
)
GO


alter table S add constraint PK_S_001 primary key(SID)
alter table S add constraint CHK_S_001 check( SSex in ('男' , '女') )


create table C
(
CID int identity(1,1) not null,
CName varchar(100) 
)


alter table C add constraint PK_C_001 primary key(CID)
alter table C add constraint UNQ_C_001 unique(CName)


create table SC
(
SID int not null, 
CID int not null,
Score numeric( 4,1 )
)


alter table SC add constraint PK_SC_001 primary key( SID , CID )
alter table SC add constraint FK_SC_001 foreign key ( SID ) references S(SID)
alter table SC add constraint FK_SC_002 foreign key ( CID ) references C(CID)
alter table SC add constraint CHK_SC_001 check ( Score between 0 and 100 )


/*
第六种,意外(缺省约束)
*/
create table test
(
id int identity(1,1) primary key,
status char(1) default('1'),
memo varchar(100)
)


insert into test(memo) values('杨广!!!')
insert into test(status , memo) values( NULL ,'鲁班!!!')
select * from test;


/*
课下作业二:旅游局的ER,表已经出来了,(约束,设计他的域)
用脚本实现
*/


/*
uniqueidentifier ==> newid() 
*/
create table test2
(
id int identity(1,1) primary key,
number int not null,
[type] char(2)
)
GO


select * from test2;


insert into test2 values( 1 , '红' )
insert into test2 values( 2 , '红' )
insert into test2 values( 3 , '红' )
insert into test2 values( 4 , '红' )
insert into test2 values( 5 , '红' )
insert into test2 values( 6 , '红' )
insert into test2 values( 7 , '红' )
insert into test2 values( 8 , '红' )
insert into test2 values( 9 , '红' )
insert into test2 values( 10 , '红' )
insert into test2 values( 11 , '红' )
insert into test2 values( 12 , '红' )
insert into test2 values( 13 , '红' )
insert into test2 values( 14 , '红' )
insert into test2 values( 15 , '红' )
insert into test2 values( 16 , '红' )
insert into test2 values( 17 , '红' )
insert into test2 values( 18 , '红' )
insert into test2 values( 19 , '红' )
insert into test2 values( 20 , '红' )
insert into test2 values( 21 , '红' )
insert into test2 values( 22 , '红' )
insert into test2 values( 23 , '红' )
insert into test2 values( 24 , '红' )
insert into test2 values( 25 , '红' )
insert into test2 values( 26 , '红' )
insert into test2 values( 27 , '红' )
insert into test2 values( 28 , '红' )
insert into test2 values( 29 , '红' )
insert into test2 values( 30 , '红' )
insert into test2 values( 31 , '红' )
insert into test2 values( 32 , '红' )
insert into test2 values( 33 , '红' )
insert into test2 values( 34 , '红' )
insert into test2 values( 35 , '红' )
insert into test2 values( 36 , '红' )


insert into test2 values( 1 , '蓝' )
insert into test2 values( 2 , '蓝' )
insert into test2 values( 3 , '蓝' )
insert into test2 values( 4 , '蓝' )
insert into test2 values( 5 , '蓝' )
insert into test2 values( 6 , '蓝' )
insert into test2 values( 7 , '蓝' )
insert into test2 values( 8 , '蓝' )
insert into test2 values( 9 , '蓝' )
insert into test2 values( 10 , '蓝' )
insert into test2 values( 11 , '蓝' )
insert into test2 values( 12 , '蓝' )
insert into test2 values( 13 , '蓝' )
insert into test2 values( 14 , '蓝' )
insert into test2 values( 15 , '蓝' )
insert into test2 values( 16 , '蓝' )


select top 6 * from test2 where type = '红' order by newid()
select top 1 * from test2 where type = '蓝' order by newid()


create table test3
(
id uniqueidentifier  primary key,
number int not null,
[type] char(2)
)
GO


insert into test3 values( newid() , 1 , '王' )
select * from test3


/*
新增的几种写法
insert into test3 values( newid() , 1 , '王' ) 我不指定具体的列,必须要求新增的数据的顺序及个数必须是对应的
insert into test(status , memo) values( NULL ,'鲁班!!!') 我指定具体的列,要求你后面新增的值和指定的列的个数及顺序对应
insert into test2 values( 1 , '红' ) 我有自增列,这个时候,不需要指明自僧列
insert into test3 values( newid() , 1 , '王' ) 如果新增的列的数据类型中有uniqueidentifier类型,那么用newid取值
*/


/*删除数据*/
delete from test3
TRUNCATE table test3
/*
相同的地方,都可以删除整个表的数据
区别:truncate不能带条件,delete是一个逻辑删除,truncate是一个物理删除。
delete删除的数据可以通过日志文件找回,但是,truncate删除的数据找不回了。
.......  效率比较低                         ........ 效率高
*/


/*
修改  insert into S values( 1002 , '杨玉环' , '女' , '1989-01-01' , '感恩寺' , 1 )
*/
update S set SName = '武则天' , SBirthday = '1841-01-01' where SID = 1002
select * from S


update S set  SBirthday = NULL where SID = 1002
--我是62年生人,38+17 = 55岁




/*
利用insert语法进行批量新增
*/
insert into test3
select 
newid() , number , type
from test2




insert into test4 
select 
newid() , number , type
from test2


/*
利用select...into语句,实现对一个新表的批量新增
*/
select *  into test4
from test2


select [type]  
into test5
from test2


/*
课下作业三:
每个表新增五条数据,新增的有意义
*/


/*
1. 数据类型
   int , bit
   numeric(p[,s])
   datetime  datetimeoffset
   char varchar , nchar nvarchar , text  ntext
   uniqueidentifier --> newid
   binary varbinary image


2. 创建表的语法 、 删除表的语法
3. 约束
主键约束
不能为空约束
检查约束
唯一约束
外键约束
缺省约束
4. 新增、修改
*/


select * from C
insert into C values( '数学' )
insert into C values( '语文' )
insert into C values( '体育' )


insert into SC values ( 1001 , 1,85 )
insert into SC values ( 1001 , 2,65 )
insert into SC values ( 1001 , 3,100 )


insert into SC values ( 1002 , 1,90 )
insert into SC values ( 1002 , 2,95 )
insert into SC values ( 1002 , 3,75 )


insert into SC values ( 1003 , 1,99 )
insert into SC values ( 1003 , 2,96 )
insert into SC values ( 1003 , 3,40 )


insert into SC values ( 1004 , 1,85 )
insert into SC values ( 1004 , 2,90 )
insert into SC values ( 1004 , 3,85 )


------------------------------------------第三天---------------------------------------------
select * from S
select * from C
select * from SC


--EX01 查询某一个表的所有数据
select * from S
--EX02 查询某一个表的某几列数据(投影) SName , SSex
select SName , SSex from S
--EX03 查询某一个表的某几列数据(投影) 给投影列起别名
select SName as 学生姓名 , SSex as 学生性别 from S
select SName  '学生姓名' , SSex '学生性别' from S
select '学生姓名'=SName   , '学生性别'=SSex  from S
--EX04 查询前2笔数据
select top 2 * from S
--EX05 查询前40%的数据
select top 40 percent * from S
--EX06 查询学生表里面性别有哪一些
select distinct SSex from S
--EX07 聚集函数 count(求元组的个数=求记录的条数) , sum(这一列的总和) , avg , max , min
--1. 求一共有几个学生
select count(*) from S
--2. 求SID为1001的学生的平均分数
select avg(Score) '平均分',sum(Score) '总分',max(Score),min(Score) from SC where SID = 1001
--3. 求CID为1这门课的最高分是多少,最低分是多少 ( 分数(SC-Score),CID(SC) )
select max(Score),min(Score) from SC where CID =1 


insert into S values( 1005 , '宋江' , '男' , '1989-01-01' , '梁山' , 1 )
insert into SC values ( 1005 , 1 , NULL )
--4. 求CID为1这门课的平均分数 
select avg(Score) from SC where CID = 1
select * from SC where CID = 1
select sum(Score)/5 from SC where CID = 1
--备注:NULL值不计算在内
select count(Score) from SC where CID = 1


--EX08 选择操作 = >= <= != <>  >  < 
--1. 求所有SID编号大于5的学生信息
select * from S where SID > 5


--EX09 AND OR
--1. 求所有在CID为1的这门课上 考了 80分以上的同学编号
--   CID =1  Score > 80
select * from SC where CID =1 and Score > 80
--2. 求所有在CID为1的这门课上 考了  不在 60-90 分之间  的同学编号
select * from SC where CID = 1 and (Score < 60 or Score > 90)


--EX10  我想找到出生日期不详的人 
select * from S where SBirthday IS NULL


--EX11  我想找到出生日期详的人 
select * from S where SBirthday IS NOT NULL


--EX12 我想找出所有CID=1上考了60-90 分之间  的同学编号
select * from SC where CID = 1 and Score between 60 and 90
--2. 求所有在CID为1的这门课上 考了  不在 60-90 分之间  的同学编号
select * from SC where CID = 1 and (Score < 60 or Score > 90)
--等效于
select * from SC where CID = 1 and Score not between 60 and 90


--EX13 IN 关键字
--找出 杨玉环 , 杨广, 张三丰 这几个同学的信息
select * from S where SName in ( '杨玉环' , '杨广' , '张三丰' )


--找出除了 杨玉环 , 杨广, 张三丰 这几个同学之外的信息
select * from S where SName not in ( '杨玉环' , '杨广' , '张三丰' )


--EX14 模糊查询
--找出所有姓杨的同学信息  % 任意个任意字符
select * from S where SName like '杨%'


--找出所有姓杨的并且名字是三个字的同学信息   _ 一个任意字符
select * from S where SName like '杨__'


--EX15 排序
-- 按照学生的性别,出生日期进行升序排序显示
select * from S order by SSex asc , SBirthday asc
-- 按照学生的性别,出生日期进行降序排序显示
select * from S order by SSex desc , SBirthday desc


--EX16 分组 group by
-- 1. 统计一下学校里面男女生的人数
/*
男  10
女  67
*/
select SSex,count(*) '人数' from S 
group by SSex


-- 2. 统计每个学生的平均成绩
/*
SID  平均成绩
1001  89
1002  30
*/
select SID , avg(Score) from SC
group by SID


-- EX17 我想求出所有平均分数高于80分的同学编号和分数,让他们参加竞赛去。
/*
SID  平均成绩
1001  89


分组前过滤用where,分组后过滤用having
*/
select SID , avg(Score) from SC
group by SID
having avg(Score) > 80


-- EX18 IN (查询语句)  --- 子查询
-- 查询所有修了  语文的学生的编号
--     语文(C)
--     SID ( SC )
select * from SC where CID = 2 --语文这门课的编号 
select CID from C where CName = '语文'




select * from SC where CID IN ( 
select CID from C where CName = '语文'
)
--或者
select * from SC where CID = ( 
select CID from C where CName = '语文'
)


--1. 求所有修了语文的学生信息
-- 语文 (C)  学生信息(S)  SC
select * from S where SID in  (1001 , 1002 , 1003 , 1004) --( 学生编号1 , 学生编号2 ... )
select SID from SC where CID = 2 -- 语文的编号  1001 1002 1003 1004
select CID from C where CName = '语文'


select * from S where SID in  (
select SID from SC where CID = (
select CID from C where CName = '语文'
)
)


-- EX19 并集  union all (不去除重复的)  不带all(去除重复的)
select * into S_History from S


select * from S
union all
select * from S_History where SSex = '男'


select * from S
union 
select * from S_History where SSex = '男'


--EX20 intersect  交集
select * from S
intersect 
select * from S_History where SSex = '男'


--EX21 EXCEPT   A - A^B  补操作
select * from S
EXCEPT 
select * from S_History where SSex = '男'


--EX22 乘操作
select * from S , S_History


--EX23 求即修了1这门课,又修了2这门课的学生编号 SC
select SID from SC where CID = 1
intersect
select SID from SC where CID = 2


--EX24 求即修了1这门课,又修了2这门课的学生信息
select * from S where SID in (
select SID from SC where CID = 1
intersect
select SID from SC where CID = 2
)


--课下作业:
--EX25 求即修了语文这门课,又修了数学这门课的学生信息
select CID from C where CName = '语文'
select CID from C where CName = '数学'


select * from S where SID in (
select SID from SC where CID = (select CID from C where CName = '语文')
intersect
select SID from SC where CID = (select CID from C where CName = '数学')
)


--EX26 修了所有课程的学生信息
-- 我们求学生的修的课数     这个课数 = 我们C表的数量
-- 我们要求出每个学生修的课的数量
select * from S where SID in (
select 
SID 
from SC 
group by SID
having
count(*) = (select count(*) from C)
)

--EX27 求2这门课的最高分
-- 求2这门课的分数
select max(score) from SC where CID = 2


--EX28 求语文这门课的最高分
select max(score) from SC where CID = (
select CID from C where CName = '语文'
)


--EX29 求语文这门课的最高分的学生信息
--  我们要看一看哪一些学生ID 语文 考了96分
--  我们要看一看哪一些学生 他在CID为2的这门课上 考了96分
select * from S where SID in (
select 
SID
from SC where CID = (
select CID from C where CName = '语文'
) and Score = (
select max(score) from SC where CID = (
select CID from C where CName = '语文'
)
)
)
-----------------------第四天----------------------------------
--多表查询 
--(1) 等值链接 , 乘操作
select * from S,SC where S.SID = SC.SID 
-- 我想求出 (学生编号,学生姓名,课程编号,课程名称,分数)
select S.SID , S.SName , SC.CID , C.CName , Score from S , SC , C
where S.SID = SC.SID and SC.CID = C.CID


--求出每个学生的平均成绩
-- (学生编号,学生姓名,平均成绩)
select 
S.SID , SName , avg(SC.Score)
from
S , SC where S.SID = SC.SID
group by S.SID , SName


insert into S values( 1006 , '李白' , '男' , '1989-01-01' , '韩国' , 1 )
select * from S 


--求出每个学生的课的数量
-- (学生编号,学生姓名,选修课数)
select 
S.SID , SName , count(*)
from
S , SC where S.SID = SC.SID
group by S.SID , SName
-- 思考?
--(2) 内链接 (内链接和等值链接在效果上是一致)  和外链接
select 
S.SID , SName , count(*)
from
S inner join SC on S.SID = SC.SID
group by S.SID , SName


--(3) 我想求出 学生的编号,姓名,课程ID , 课程名称,分数
select 
S.SID , SName , SC.CID , CName , Score
from S inner join SC on S.SID = SC.SID
inner join C on SC.CID = C.CID


--(4) 左外链接
select 
S.SID , SName , SC.CID , SC.Score
from
S left outer join SC on S.SID = SC.SID


select 
S.SID , SName , count(SC.CID) '修的课数'
from
S left outer join SC on S.SID = SC.SID
group by S.SID , SName


select 
S.SID , SName , SC.CID , CName , Score
from S left outer join SC on S.SID = SC.SID
left outer join C on SC.CID = C.CID


-- (5) 右外联 right outer join
select 
S.SID , SName , SC.CID , SC.Score
from
SC right outer join S on S.SID = SC.SID


-- SOME=ANY , ALL
select * from SC where Score >ALL (
select Score from SC where CID = 2 --求2这门课所有的分数
-- 65 , 95 , 96 , 90
)


select * from SC where Score select Score from SC where CID = 2 --求2这门课所有的分数
-- 65 , 95 , 96 , 90
)


--(6) 排名函数
select 
RANK( ) OVER ( order by Score Desc  ) '名次' , *
from SC where CID = 1 


select 
DENSE_RANK ( ) OVER ( order by Score Desc  ) '名次' , *
from SC where CID = 1 


-- (7) 子查询 求全班数学前三名的同学
select * from (
select 
DENSE_RANK ( ) OVER ( order by Score Desc  ) '名次' , *
from SC where CID = (
select CID from C where CName = '数学'

) A where A.名次 <= 3


-- (8) 学生表的信息,修课的数量
select
S.SID , S.SName , 修课的数量 = (
select count(*) from SC where S.SID = SC.SID )
from 
S


-- 课堂作业一:
-- 1. 求哪一些学生没有修课
select * from S where SID not in(
select SID from SC
)


select 
S.*
from
S left outer join SC on S.SID = SC.SID
where SC.CID is null


--SP. 
select * from S where SID  in(
select SID from SC
)


select 
distinct S.*
from
S inner join SC on S.SID = SC.SID


--  exists 存在
select 
*
from 
S where exists ( select * from C where 2 = 1  )


-- 我想查询出所有修了课的学生
select 
*
from 
S where exists ( select * from SC where S.SID = SC.SID )


-- 2. 求哪一个学生分数没有低于80分的 
--  学生的分数都高于80
select * from S where SID not in (
select SID from SC where Score < 80
)  and exists ( select * from SC where S.SID = SC.SID )


----------------------T - SQL-----------------------
/*
1. 申明变量
2. 给变量赋值
3. 读变量的值
*/
declare @name varchar(30)
set @name = '张三丰'
select @name = '战死翁'
print @name


--1. 求SID=1002的学生的平均成绩,并打印出来。
declare @avg_score int
declare @sum_score int
select @avg_score = avg(score) ,@sum_score = sum(score)  from sc 
where sid = 1002
print @avg_score 
print @sum_score


--2. 分支  求SID=1002的学生的平均成绩,如果是90分以上,则输出优秀
-- 如果是80分以上,输出良好,70分以上,输出一般,60分以上,输出及格
-- 60分以下,不及格
declare @avg_score int
select @avg_score = avg(score) from SC where SID = 1002
if @avg_score >= 90 
print '优秀'
else if @avg_score >=80 
print '良好'
else if @avg_score >= 70 
print '一般'
else if @avg_score >= 60 
print '及格'
else
print '不及格'


select 
SID , SName , 
CASE SStatus 
WHEN 1 THEN '在学'
WHEN 0 THEN '离校'
END '状态'
from S -- 1的时候显示在学,如果显示0的时候,离校


declare @avg_score int
declare @status char(6)
select @avg_score = avg(score) from SC where SID = 1002
-- CASE WHEN
SET @status = CASE 
WHEN @avg_score >= 90 THEN '优秀'
WHEN @avg_score >= 80 THEN '良好'
ELSE '其他'
END
print @status


--课下作业:----
--1. 用T-SQL 实现下面的功能
--   查询学号为1003的学生,如果出生日期是NULL,则更新该生的生日为
--   2005-01-02 ; 如果不为NULL,则更新生日为 2000-01-02
declare @birthday datetime
select @birthday = SBirthday from S where SID = 1003
if @birthday is null
begin
update S set SBirthday = '2005-01-02' where SID = 1003
end
else
begin
update S set SBirthday = '2000-01-02' where SID = 1003
end
select * from S


--2. 新建一个表  结构如下( 教师编号 , 教师姓名, 课程编号 )
--   1个老师只能教1门课,但是1门课可以被1个老师讲授
--  课程编号是外键(C(CID))
create table T
(
TID int identity(1,1) primary key,
TName varchar(30) not null,
CID int,
foreign key(CID) references C(CID)
)


--3. LEFT( 字段 , 1 )
-- 求这个学校 姓氏人数的 分布
-- 杨  2
-- 张  3


select left(SName , 1) , count(*) from S
group by left(SName , 1)


--4. 用T-SQL求出 杨玉环是哪一个星座的?
declare @month int
declare @day int
declare @xingzuo varchar(20)
select @month = month( SBirthday ) , @day = day( SBirthday ) from S where SName = '张三丰'
set @xingzuo = case 
when (( @month = 4 and @day > 21  ) or ( @month = 5 and @day < 21  )) 
then '金牛座'
when (( @month = 5 and @day > 21  ) or ( @month = 6 and @day < 18  )) 
then '双子座'
else '不知名星座'
end
print @xingzuo


select * from S where SName = '张三丰'






-----------------------第五天----------------------------------
-- 循环 WIHLE 布尔表达式 begin  一条一条的语句   end
-- 打印五个下午好
declare @count int  --计数器
set @count = 0
while ( @count < 5 )
begin
print '下午好'
set @count = @count + 1
end


-- break   continue
declare @count int  --计数器
set @count = 0
while ( @count < 5 )
begin
if @count = 2
break;


set @count = @count + 1
print '下午好' + cast(@count as varchar(10))
end


declare @count int  --计数器
set @count = 0
while ( @count < 5 )
begin
set @count = @count + 1


if @count = 2
begin
continue
end


print '下午好' + cast(@count as varchar(10))
end
-- 函数
select @@Version --全局的,系统级别
select @@error


-- 1. DateAdd 在指定的日期上添加一个指定的时间,比如:
--  我可以求得当前日期推后三天,是哪一天?


-- 小明是2005-01-01出生,小明的妹妹450天以后出生,
--       问小明的妹妹是哪一天出生的。
--       小明的二表妹是78个星期后出生的,问他二表妹的生日
select dateadd( dd , 450 ,'2005-01-01')
select dateadd( ww , 78 ,'2005-01-01')


-- DateDiff 求两个时间差
-- 小明是2005-01-01出生,小明的妹妹是2007-05-21出生的,
--   问小明和小明的妹妹差多少个周
select datediff( hh ,'2005-01-01', '2007-05-21' )


-- 统计S表中,每个月份过生日的人数
select 
datepart( mm ,SBirthday) , count(*)
from
S
group by
datepart( mm ,SBirthday)


select day( getdate() )
select month( getdate() )
select year( getdate() )


-- 四舍五入
select round( 89.56 , 1 )


--LEFT 求所有姓杨的人数
select count(*) from S where LEFT( SName , 1 ) = '杨'


-- RIGHT
select count(*) from S where RIGHT( SName , 1 ) = '丰'


-- LTRIM , RTRIM
select RTRIM(LTRIM('    A    ')), '    A'


--SUBSTRING 
select SUBSTRING( '你是大坏蛋' , 1 , 1 )


--REPLACE
select REPLACE( '你是大坏蛋' , '你' , '它' )


-- 课下作业一:小明的爸爸要在2005-2-23退休了,拉着小明的手,对小明说,
--   你要继承我的事业,我是一个打鱼,打鱼要三天打鱼,两天晒网。
--   问小明在今天是打鱼还是晒网


-- 课下作业二:求n的斐波拉切数列
-- 课下作业三:求1000以内的素数


-- 游标 (遍历结果集的游标-->显示游标)


DECLARE @SID INT
DECLARE @SName varchar(30)


DECLARE MyCursor CURSOR FOR
SELECT SID ,SName FROM S 


OPEN MyCursor 


FETCH NEXT FROM MyCursor INTO @SID,@SName
PRINT CAST(@SID AS VARCHAR(20)) + @SName


WHILE @@FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM MyCursor INTO @SID,@SName
PRINT CAST(@SID AS VARCHAR(20)) + @SName
END


CLOSE MyCursor
DEALLOCATE MyCursor


-- 课下作业四,遍历学生分数,如果这个学生分数小于60分,我就给这个学生提高5分。
-- 用游标


-- 视图 View : 里面封装复杂的SQL
create view v_student
as
select 
datepart( mm ,SBirthday) '月' , count(*)  '人数'
from
S
group by
datepart( mm ,SBirthday)


create view v_student1
as
select 
S.SID , SName , SC.CID , CName , Score
from S left outer join SC on S.SID = SC.SID
left outer join C on SC.CID = C.CID




create view v_student2
as
select * from v_student


--使用视图就和使用表一样
select * from v_student2


alter view v_update_student
as
select top 1 * from S


update v_update_student set SName = '张思丰' where SName = '张三丰'
select * from v_update_student


update v_student set SName = '张三丰' where SName = '张思丰'


-- 视图的特征:
/*
视图是一个虚拟表,其内容由查询SQL语句定义。
同真实的表一样,视图包含一系列带有名称的列和行数据。
行和列数据来自于定义视图的查询所引用的表,并且在引用视图时动态生成。
对其中所引用的基础表来说,视图的作用类似于筛选。
定义视图的筛选可以来自当前或其他数据库的一个或多个表,或者其他视图。
通过视图进行查询没有任何限制,通过它们进行数据修改时的限制也不少。
*/


drop view v_student
select * from v_student


--索引:为了检索的速度
create INDEX IDX_Student ON S(SSex);
create unique INDEX IDX_Student_sex ON S(SSex);


select * from S where SSex = '男'
drop index S.IDX_Student --删除索引


-- 备注:什么时候用索引
--       当一个列的数据值重复的比较多的时候
--       一般情况下 占10%以内
--       主键会默认给他创建主键索引( 唯一的索引,而且不能为空 )


--预习:存储过程,函数,触发器
create function my_fun ( @STR1 varchar(30) , @STR2 varchar(30) )
returns varchar(60)
as
begin
return @STR1 + @STR2
end


select dbo.my_fun( '张三丰' , '大好人' )
select dbo.my_fun( SName , SSex ) from S


drop function my_fun


select getdate()



















































































 


































 

你可能感兴趣的:(考研之路--开始)