创建数据库
CREATEDATABASEdatabase_name
[ON
[PRIMARY][
[,...n]
[,[,...n]]
[LOGON{[,...n]}]
]
[COLLATEcollation_name]
[WITH]
]
修改数据库
ALTERDATABASEdatabase_name
{
|
|
|MODIFYNAME=new_database_name
|COLLATEcollation_name
}
[例3.6]将数据库名mytest更改为mytest1。
AlterdatabasemytestMODIFYNAME=mytest1
[例3.7]将一个5MB的数据文件添加到AdventureWorks数据库。
ALTERDATABASEAdventureWorks
ADDFILE
(
NAME=Test1dat2,
FILENAME='C:\ProgramFiles\MicrosoftSQLServer
\MSSQL.1\MSSQL\DATA\\t1dat2.ndf'',
SIZE=5MB,
MAXSIZE=100MB,
FILEGROWTH=5MB
)
[例3.8]删除上例中添加的数据库文件。
ALTERDATABASEAdventureWorks
REMOVEFILETest1dat2
[例3.9]移动数据库文件的位置。
ALTERDATABASEAdventureWorks
MODIFYFILE
(
NAME=Test1dat2,
FILENAME=N'c:\t1dat2.ndf'
)
[例3.10]更改数据库文件大小。
ALTERDATABASEAdventureWorks
MODIFYFILE
(NAME=test1dat3,
SIZE=20MB
)
[例3.12]更改数据库选项。
ALTERDATABASEAdventureWorksSETSINGLE_USER--单用户
ALTERDATABASEAdventureWorksSETREAD_ONLY–只读
ALTERDATABASEAdventureWorksSETAUTO_SHRINKON--自动收缩
GO
[例3.14]将AdventureWorks用户数据库中名为TestDat1的文件的大小收缩到10MB。
DBCCSHRINKFILE(TestDat1,10)
删除数据库
使用DROPDATABASE删除数据库。其语法格式为:
DROPDATABASE{database_name}[,...n]
[例3.15]删除数据库
DROPDATABASEmyTest1--删除单个数据库。
DROPDATABASEmyTest2,myTest3--删除多个数据库
用SQL命令创建数据表
基本语法如下:
CREATETABLE表名
(
列名1数据类型和长度1列属性1,
列名2数据类型和长度2列属性2,
…………
列名n数据类型和长度n列属性n
)
USE学生选课
GO
CREATETABLEStudent
(
SnointPRIMARYKEYIDENTITY(20050301,1),
Snamevarchar(20)NOTNULL,
Ssexchar(2),
Sagesmallint,
Sdeptvarchar(20)
)
CREATETABLESgrade
(
Snoint,
Grade1int,
Grade2int,
Grade3int,
TotalASGrade1+Grade2+grade3
)
通过sp_help存储过程来查看表结构信息。
ALTERTABLE表名ADD列名数据类型和长度列属性
【例4.1】在表Student中新增一列“入学年月”,列名为Sentrance,数据类型为datetime,允许空值。
执行以下语句:
ALTERTABLEStudentADDSentrancedatetime
ALTERTABLE表名
ALTERCOLUMN列名新数据类型和长度新列属性
例如,【例4.1】中创建的Sentrance列是datetime类型,并且不允许为空。现在要将该列改为smalldatetime类型,并且允许为空。
SQL语句如下:
ALTERTABLEStudent
ALTERCOLUMNSentrancesmalldatetimeNULL
ALTERTABLE表名DROPCOLUMN列名
例如,要删除Student表中的Sentrance列,可以执行下面的SQL语句。
ALTERTABLEStudentDROPCOLUMNSentrance
可以使用sp_rename存储过程对表和表中的列进行重命名,重命名的基本语法为:
sp_rename原对象名,新对象名
例如,如果想将Student表改名为StudentInfo,可以执行以下SQL语句:
sp_renameStudent,StudentInfo
DROPTABLE表名
【例4.2】删除“学生选课”数据库中的exam表。
USE学生选课
GO
DROPTABLEexam
0:162010-10-19
用INSERT语句插入数据
INSERT语句的基本语法:
INSERTINTO表名(列名1,列名2,……,列名n)
VALUES(值1,值2,……,值n)
INSERT子句指定要插入的数据表名,并且可以同时指定表的列名称。
VALUES子句指定要插入的数据。
例:
USE学生选课
GO
INSERTINTOStudent
(Sname,Ssex,Sage,Sdep)
VALUES('曾玉林','男',20,'CS')
使用SELECT语句插入数据的基本语法形式为:
INSERTINTO表名(列名1,列名2,……,列名n)
SELECT语句
UPDATE语句基本语法:
UPDATE表名
SET列名1=值1,列名2=值2,……,列名n=值n
WHERE更新条件表达式
【例4.3】将学生表Student中“刘尘”所属的由CS改为SS。
USE学生选课
GO
UPDATEStudentSETSdep='SS'
WHERESname='刘尘'
【例4.4】将所有学生的年龄增加1岁。
USE学生选课
GO
UPDATEStudentSETSage=Sage+1
使用DELETE语句删除数据的基本语法形式如下:
DELETEFROM表名
WHERE条件表达式
【例4.5】删除Exam表中为“刘尘”的数据记录。
USE学生选课
GO
DELETEFROMExam
WHEREEname='刘尘‘
【例5.1】查询全体学生的及其出生年份。
SELECTSname,2007-Sage
FROMStudent
【例5.2】查询选修了课程的学生。
SELECTSno
FROMSC
或
SELECTDISTINCTSno
FROMSC
【例5.3】查询Student表中所有年龄大于19岁的学生信息。
SELECT*FROMStudent
WHERESage>19
或者
SELECT*FROMStudent
WHERENOTSage<=19
【例5.4】查询所有计算机(“CS”)的学生和。
SELECTSno,Sname
FROMStudent
WHERESdep='CS'
如果想查询所有非计算机的学生名单,则可以使用:
SELECTSno,Sname
FROMStudent
WHERESdep<>'CS'
【例5.5】查询Student表中所有男生或者年龄大于19岁的学生和年龄。
SELECTSname,Sage
FROMStudent
WHERESsex='男'ORSage>19
LIKE子句中的通配符
通配符含义
%代表任意长度(长度可以为0)的字符串
_代表任意单个字符
[]指定范围或集合中的任意单个字符
[^]不在指定范围或集合中的任意单个字符
下面是一些带有通配符的示例:
LIKE'AB%'返回以“AB”开始的任意字符串。
LIKE'%ABC'返回以“ABC”结束的任意字符串。
LIKE'%ABC%'返回包含“ABC”的任意字符串。
LIKE'_AB'返回以“AB”结束的3个字符的字符串。
LIKE'[ACE]%'返回以“A”、“C”、“E”开始的任意字符串。
LIKE'[A-Z]ing'返回4个字符长的字符串,结尾是“ing”,第1个字符的范围是从A到Z。
LIKE'L[^a]%'返回以“L”开始、第2个字符不是“a”的任意字符串。
【例5.6】查询所有姓刘的学生的、和性别。
SELECTSno,Sname,Ssex
FROMStudent
WHERESnameLIKE'刘%‘
【例5.7】查询所有不姓刘的学生和。
SELECTSno,Sname
FROMStudent
WHERESnameNOTLIKE'刘%'
【例5.8】查询中第二个字为“勇”字的学生和。
SELECTSno,Sname
FROMStudent
WHERESnameLIKE'_勇%'
【例5.9】查询DB_Design课程的课程号和学分。
SELECTCno,Ccredit
FROMCourse
WHERECnameLIKE'DB\_Design'ESCAPE'\'
ESCAPE'\'表示“\”为转义字符,这样匹配字符串中紧跟在“\”后面的字符“_”就不再具有通配符的含义,而是转义为普通的“_”字符处理。
【例5.10】查询年龄在19~22之间的学生的、年龄和所属院系。
SELECTSname,Sage,Sdep
FROMStudentWHERESageBETWEEN19AND22
【例5.11】查询年龄不在19~22之间的学生的、年龄和所属院系。
SELECTSname,Sage,Sdep
FROMStudentWHERESageNOTBETWEEN19AND22
在SQL语言中,一个SELECT…FROM…WHERE…语句称为一个查询块。将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询。
例如:SELECTSname
FROMStudent
WHERESnoIN
(SELECTSno
FROMSC
WHERECno='2');
【例5.12】查询与“李勇”在同一个院系学习的学生信息。
先分步完成此查询,然后再构造嵌套查询。
(1)确定“刘尘”所在的系名。
SELECTSdep
FROMStudent
WHERESname='刘尘'
查找结果为SS。
(2)查找所有在SS系学习的学生、、系别信息。
SELECTSno,Sname,Sdep
FROMStudent
WHERESdep='SS'
将第(1)步查询嵌入到第(2)步查询中,构造出嵌套查询:
SELECTSno,Sname,Sdep
FROMStudent
WHERESdepIN
(SELECTSdep
FROMStudent
WHERESname='刘尘')
【例5.13】查询选修了课程名为“数据库原理”的学生和。
本查询涉及、和课程名3个属性。和存放在Student表中,课程名存放在Course表中,这两个表之间没有直接的联系,所以需要通过SC表建立二者之间的联系。因此本查询实际上涉及3个关系。
SELECTSno,Sname
FROMStudent
WHERESnoIN
(SELECTSno
FROMSC
WHERECnoIN
(SELECTCno
FROMCourse
WHERECname=‘数据库原理’))
例如,在【例5.12】中,由于一个学生只可能在一个系学习,也就是说子查询的结果是一个值,因此可以用“=”代替“IN”,其SQL语句如下:
SELECTSno,Sname,Sdep
FROMStudent
WHERESdep=
(SELECTSdep
FROMStudent
WHERESname='刘尘')
【例5.14】找出每个学生超过他选修课程平均成绩的课程号。
SELECTSno,Cno
FROMSCx
WHEREGrade>=
(SELECTAVG(Grade)
FROMSCy
WHEREy.Sno=x.Sno)
子查询返回单值时,可以用比较运算符,但返回多值时,要用ANY或ALL谓词修饰符。而使用ANY或ALL谓词时,必须同时使用比较运算符。其语义为:
>ANY大于子查询结果中的某个值
>ALL大于子查询结果中的所有值
>=ANY大于等于子查询结果中的某个值
>=ALL大于等于子查询结果中的所有值
<=ANY小于等于子查询结果中的某个值
<=ALL小于等于子查询结果中的所有值
=ANY等于子查询结果中的某个值
=ALL等于子查询结果中的所有值(通常没有实际意义)
!=(或<>)ANY不等于子查询结果中的某个值
!=(或<>)ALL不等于子查询结果中的任何一个值
【例5.15】查询其他系中比计算机系某一学生年龄小的学生、年龄和所属院系。
SELECTSname,Sage,Sdep
FROMStudent
WHERESage FROMStudent
WHERESdep='CS')
ANDSdep!='CS‘
该查询也可以用聚集函数来实现。首先用子查询找出计算机系学生的最大年龄(20),然后在父查询中查询所有非计算机系其年龄小于20的学生。SQL语句如下:
SELECTSname,Sage,Sdep
FROMStudent
WHERESage<(SELECTMAX(Sage)
FROMStudent
WHERESdep='CS')
ANDSdep!='CS'
【例5.16】查询其他系中比计算机系所有学生年龄都小的学生、年龄和所属院系。
SELECTSname,Sage,Sdep
FROMStudentWHERESage FROMStudent
WHERESdep='CS')
ANDSdep!='CS‘
本查询同样也可以用聚集函数来实现,SQL语句如下:
SELECTSname,Sage,Sdep
FROMStudentWHERESage<(SELECTMIN(Sage)
FROMStudent
WHERESdep='CS')
ANDSdep!='CS'
【例5.17】查询所有选修了1号课程的学生。
本查询涉及Student和SC关系。可以在Student表中依次取每个元组的Sno值,再用这个值去检查SC关系。若SC中存在这样的元组,其Sno值等于此Student.Sno值,并且其课程号Cno为1,则取此Student.Sname送入结果集中。
SELECTSname
FROMStudent
WHEREEXISTS(SELECT*
FROMSC
WHERESno=Student.SnoANDCno='1')
【例5.18】查询所有没有选修1号课程的学生。
SELECTSname
FROMStudent
WHERENOTEXISTS
(SELECT*
FROMSC
WHERESno=Student.SnoANDCno='1')
【例5.19】查询选修所有全部课程的学生。
SELECTSname
FROMStudent
WHERENOTEXISTS
????(SELECT*
?????FROMCourse
?????WHERENOTEXISTS
?????????(SELECT*
???????????FROMSC
???????????WHERESno=Student.Sno
ANDCno=Course.Cno)
例如,带有IN谓词的【例5.12】可以用如下带EXISTS谓词的子查询替换:
SELECTSno,Sname,Sdep
FROMStudentS1
WHEREEXISTS
(SELECT*
FROMStudentS2
WHERES2.Sdep=S1.SdepANDS2.Sname='刘尘')
【例5.20】查询选修了课程1或者选修了课程2的学生。
本查询实际上就是查询选修了课程1的学生集合与选修了课程2的学生集合的并集。
SELECTSno
FROMSC
WHERECno='1'
UNIONALL
SELECTSno
FROMSC
WHERECno='2'
【例5.21】查询既选修了课程1又选修了课程2的学生。
本查询实际上就是查询选修了课程1的学生集合与选修了课程2的学生集合的交集。SQL语句如下:
SELECTSno
FROMSC
WHERECno='1'
INTERSECT
SELECTSno
FROMSC
WHERECno='2'
【例5.22】查询计算机系的学生与年龄不大于19岁的学生的差集。
SELECT*
FROMStudent
WHERESdep='CS'
EXCEPT
SELECT*
FROMStudent
WHERESage<=19
本例实际上等价于查询计算机系中年龄大于19岁的学生信息,也可以用下面的SQL语句实现:
SELECT*
FROMStudent
WHERESdep='CS'ANDSage>19
【例5.23】查询每个学生选修课程的情况。
学生情况存放在Student表中,学生选课情况存放在SC表中,所以本查询实际上涉及Student与SC两个表。这两个表之间的联系通过公共属性Sno实现。
法(一):在FROM子句中指定连接
SELECTStudent.*,SC.*
FROMStudentINNERJOINSC
ONStudent.Sno=SC.Sno
法(二):在WHERE子句中指定连接
SELECTStudent.*,SC.*
FROMStudent,SC
WHEREStudent.Sno=SC.Sno
【例5.24】查询每个学生选修课程成绩大于80′的情况。
学生情况存放在Student表中,学生选课情况存放在SC表中,所以本查询实际上涉及Student与SC两个表。这两个表之间的联系是通过公共属性Sno实现的。
法(一):在FROM子句中指定连接
SELECTStudent.*,SC.*
FROMStudentINNERJOINSC
ONStudent.Sno=SC.SnoANDSC.Grade>80
法(二):在WHERE子句中指定连接
SELECTStudent.*,SC.*
FROMStudent,SC
WHEREStudent.Sno=SC.SnoANDSC.Grade>80
例如,在【例5.24】中,查询每个学生选修课程的情况,并去掉重复列。可以使用下面的SQL语句:
SELECTStudent.Sno,Sname,Sage,Sdep,Cno,Grade
FROMStudentINNERJOINSC
ONStudent.Sno=SC.Sno
同样地,也可以在WHERE子句中指定连接条件进行查询:
SELECTStudent.Sno,Sname,Sage,Sdep,Cno,Grade
FROMStudent,SC
WHEREStudent.Sno=SC.Sno
【例5.25】查找每一门课程的间接先修课(即先修课的先修课)。
要查询每一门课程的间接先修课,在“课程”表Course关系中,只有每门课的直接先修课信息,而没有先修课的先修课,要得到这个信息,必须先对一门课程找到其先修课,再按此先修课的课程号,查找它的先修课程,这相当于将Course表与其自身连接后,取第一个副本的课程号与第二个副本的先修课号作为目标列中的属性。
具体写SQL语句时,为清楚起见,可以为Course表取两个别名,一个是FIRST,另一个是SECOND,也可以在考虑问题时就把Course表想成是两个完全一样的表,一个是FIRST表,另一个是SECOND表。
完成该查询的SQL语句为:
SELECTFIRST.Cno,SECOND.Cpno
FROMCourseFIRSTINNERJOINCourseSECOND
ONFIRST.Cpno=SECOND.Cno
该语句也可以写成:
SELECTFIRST.Cno,SECOND.Cpno
FROMCourseFIRST,CourseSECOND
WHEREFIRST.Cpno=SECOND.Cno
例5.26】查询所有学生选修课程的情况,包括没有选修课程的学生。
本例和【例5.23】不同的地方就在于,【例5.23】只需输出有选修课程的学生信息,而本例却必须输出全部学生信息。因此,必须使用外连接才能实现本例查询。SQL语句如下:
SELECTStudent.*,SC.*
FROMStudentLEFTOUTERJOINSC
ONStudent.Sno=SC.Sno
在该查询语句中,使用了左外连接。所以Student表中的数据将全部输出,而表中不满足查询条件的数据记录在对应的SC表中都用NULL表示。
本例也可以用右外连接来完成。这时只需要把Student表和SC表的位置调换一下即可。
SELECTStudent.*,SC.*
FROMSCRIGHTOUTERJOINStudent
ONStudent.Sno=SC.Sno
【例5.27】查询所有学生选修课程的情况,以及所有课程的选课记录。
要求显示学生选修课程的情况和所有的选课记录,可以使用全外连接来实现。SQL语句如下:
SELECTStudent.Sno,Sname,Ssex,Sage,Sdep,Cno,Grade
FROMStudentFULLOUTERJOINSC
ONStudent.Sno=SC.Sno
【例5.28】查询选修了2号课程的学生及其成绩,并按分数降序输出结果。
SELECT?Sno,Grade
FROM?SC
WHERE?Cno=?'2'
ORDER?BY?Grade?DESC
【例5.29】查询全体学生信息,查询结果按所在系的系名升序排列,同一个系中的学生按年龄降序排列。
SELECT?*FROM?Student
ORDER?BY?Sdep,Sage?DESC
【例5.30】查询班内前5个学生的信息。
SELECTTOP(5)*
FROMStudent
ORDERBYSno
本查询先将结果集中的数据按Sno升序排序,然后取出前5个输出显示。
【例5.31】查询选课成绩排名在前30%的学生、和成绩。
SELECTTOP(30)PERCENTSC.Sno,Sname,Grade
FROMSC,Student
WHERESC.Sno=Student.Sno
ORDERBYGradeDESC
本查询先通过连接查询得到所有学生的选课记录,然后将得到的记录按照Grade降序排序,再从排序后的记录里取前30%进行输出。
有的读者或许会问,如果设定列出5行数据,但是第6行、第7行甚至更多行的数据如果和第5行一样的话,那么这些行的数据是否会显示?例如在【例5.31】中,结果集列出了3行数据,假设第4行数据中Grade值也是89的话,那不是就丢失了一部分可以使用的信息吗?要解决这个问题很简单,只需要在TOP子句后使用WITHTIES子句就可以了。例如同样在【例5.31】中,如果将SELECT子句改为:
SELECTTOP(30)PERCENTWITHTIESSC.Sno,Sname,Grade
FROMSC,Student
WHERESC.Sno=Student.Sno
ORDERBYGradeDESC
就能避免出现上述问题。
【例5.32】查询学生总人数。
SELECT?COUNT(*)
FROM?Student
【例5.33】查询选修了课程的学生人数。
由于一个学生可能选择多门课程,所以在计算时要要避免一个学生重复计数。所以可以使用DISTINCT关键字对学生Sno进行限定,保证同一个只计数一次。
SELECT?COUNT(DISTINCT?Sno)
FROM?SC
【例5.34】计算1号课程的学生平均成绩。
SELECT?AVG(Grade)
FROM?SC
WHERE?Cno=?'1'
【例5.35】查询选修1号课程的学生的最高分数。
SELECT?选修1号课程的最高分数=MAX(Grade)
FROM?SC
WHERE?Cno=?'1'
该语句为结果集中的列定义了一个新标题“选修1号课程的最高分数”
本查询还可以写成:
SELECT?MAX(Grade)选修1号课程的最高分数
FROM?SC
WHERE?Cno=?'1'
【例5.36】查询所有的课程号及相应的选课人数。
SELECT?Cno,COUNT(Sno)AS选课人数
FROM?SC
GROUP?BY?Cno
【例5.37】查询选修了2门以上课程的学生。
SELECT?Sno
FROM?SC
GROUP?BY?Sno
HAVING?COUNT(*)?>2
【例5.38】查询有3门以上课程是90分以上的学生及(90分以上的)课程数。
SELECT?Sno,?COUNT(*)
FROM?SC
WHERE?Grade>90
GROUP?BY?Sno
HAVING?COUNT(*)>3?