例:创建数据库“STUDENT2”,包含一个主数据文件和一个事务日志文件。
主数据文件的逻辑名为“STUDENT2_DATA”,操作系统文件名为“STUDENT2_DATA.MDF”,初始容量大小为5M,最大容量为20M,文件的增长量为20%。
事务日志文件的逻辑文件名为“STUDENT2_LOG”,物理文件名为“STUDENT2_LOG.LDF”,初始容量大小为5M,最大容量为10M,文件增长量为2M。
数据文件与事务日志文件分别存放在E盘和G盘的“DATA”
文件夹中。
首先在E盘和G盘各创建一个新的文件夹,名称是“DATA”。 CREATE DATABASE STUDENT2
ON
PRIMARY
(NAME = ‘STUDENT2_DATA’,
FILENAME = ‘D:\DATA\STUDENT2_DATA.MDF’ ,
SIZE = 5MB,
MAXSIZE = 20MB,
FILEGROWTH = 20%)
LOG ON
(NAME =‘STUDENT2_LOG’,
FILENAME = ‘G:\DATA\ STUDENT2_LOG. LDF’,
SIZE = 5MB,
MAXSIZE = 10MB,
FILEGROWTH = 2MB)
例:创建一个指定多个数据文件和日志文件的数据库。该数据库名称为STUDENTS,有1个5MB和1个10MB的数据文件和2个5MB的事务日志文件。
数据文件逻辑名称为STUDENTS1和STUDENTS2,物理文件名为STUDENTS1.mdf和STUDENTS2.ndf。主文件是STUDENTS1,由PRIMARY指定,两个数据文件的最大尺寸分别为无限大和100MB,增长速度分别为10%和1MB。
事务日志文件的逻辑名为STUDENTSLOG1和STUDENTSLOG2,物理文件名为STUDENTSLOG1.ldf和STUDENTSLOG2.ldf,最大尺寸均为50MB,文件增长速度为1MB。
要求数据文件和日志文件分别存放在E盘和G盘的DATA文件夹下。
CREATE
DATABASE STUDENTS
ON PRIMARY
(NAME=STUDENTS1,
FILENAME=‘E:\DATA\STUDENTS1.mdf’,
SIZE=5,
MAXSIZE=unlimited,
FILEGROWTH=10%),
FILEGROUP FILEG1
(NAME= STUDENTS2,
FILENAME=‘E:\DATA\STUDENTS2.ndf’,
SIZE=10,
MAXSIZE=100,
FILEGROWTH=1)
LOG ON
(NAME=STUDENTSLOG1,
FILENAME=‘G:\DATA\STUDENTSLOG1.ldf’,
SIZE=5,
MAXSIZE=50,
FILEGROWTH=1),
(NAME=STUDENTSLOG2,
FILENAME=‘G:\DATA\STUDENTSLOG2.ldf’,
SIZE=5,
MAXSIZE=50,
filegrowth=1)
例:为STUDENT2数据库增加容量,原来数据文件STUDENT2_DATA的初始分配空间为5M,现在将STUDENT2_DATA的分配空间增加至20M。
ALTER DATABASE STUDENT2
MODIFY
FILE
(NAME= STUDENT2_DATA,
SIZE=20MB)
【例】为数据库STUDENT2 增加数据文件STUDENT2_DATA1,初始大小10M,最大50M,按照5%增长。
ALTER DATABASE STUDENT2
ADD
FILE
(NAME = ‘STUDENT2_DATA1’,
FILENAME = ‘F:\DATA\ STUDENT2_DATA1.NDF’,
SIZE = 10MB,
MAXSIZE = 50MB,
FILEGROWTH = 5%)
【例】将数据库STUDENT2 中增加的数据文件STUDENT2_DATA1删除。
ALTER DATABASE STUDENT2
REMOVE FILE STUDENT2_DATA1
删除数据库
如,DROP
DATABASE STUDENT2
例:在数据库“STUDENT1”创建学生信息表(XS),包括学号(主键)、姓名、性别字段。其中性别字段只能接受“男”或“女”,不能接受其他数据。
USE STUDENT1
GO
CREATE
TABLE XS
(学号
char(12) PRIMARY KEY,
姓名 char(20) ,
性别
nchar(1) CONSTRAINT chk_sex CHECK(性别 =‘男’ or 性别 = ‘女’)
)
例:在数据库“teaching”下创建“课程表(course)”,表结构如下所示。
USE
teaching
GO
CREATE
TABLE course
(cno char(4) PRIMARY
KEY,
cname nvarchar(20) NOT NULL ,
classhour tinyint,
credit tinyint
)
例:在XS表中修改“姓名”字段的属性,使该字段的数据类型为nvarchar(10),允许为空。
USE STUDENT1
GO
ALTER
TABLE XS
ALTER
COLUMN 姓名
nvarchar(10) NULL
例:在学生信息表XS中添加“年龄”字段,数据类型为整型,可以为空。
USE STUDENT1
GO
ALTER
TABLE XS
ADD 年龄 int
例:删除学生信息表XS中的“年龄”字段。
USE STUDENT1
GO
ALTER
TABLE XS
DROP
COLUMN 年龄
USE STUDENT1
GO
CREATE
TABLE XS
(
学号 char(6) PRIMARY KEY,
身份证号 char(20) ,
姓名 char(8) NOT NULL,
专业名 varchar(10)
)
USE STUDENT1
GO
CREATE
TABLE XS1
(
学号 char(6) PRIMARY KEY,
身份证号 char(20) UNIQUE,
姓名 nvarchar(8) NOT NULL,
专业名 nvarchar(10),
)
USE STUDENT1
GO
CREATE TABLE XS1
( 学号 char(6) PRIMARY KEY,
身份证号 char(18)
UNIQUE,
姓名 nvarchar(8) NOT NULL,
专业名 nvarchar(10),
性别 nchar(1) CHECK (性别=‘男’ or 性别=‘女’)
)
USE STUDENT1
GO
CREATE
TABLE ST
(学号 char(6) PRIMARY KEY,
身份证号 char(18) UNIQUE,
姓名 nvarchar(8) NOT NULL,
专业名 nvarchar(10),
性别 nchar(1) CONSTRAINT chk_1
CHECK (性别=‘男’ or 性别=‘女’),
出生时间 smalldatetime NOT NULL,
总学分 tinyint,
入学日期 datetime DEFAULT getdate( )
)
通过创建外键约束可以实现表和表之间的关联关系。
例: 外键和通过表约束设置主键的例子:
USE STUDENT1
GO
CREATE TABLE SC
( 学号 char (6) FOREIGN
KEY REFERENCES ST(学号),
课程号 char(4),
成绩 int ,
PRIMARY KEY(学号,课程号)
)
例:在STUDENT1数据库的学生(ST)表中插入一行数据。
USE STUDENT1
GO
INSERT
into ST(学号,姓名,性别,出生时间)
VALUES(‘150111’,‘杨丽’,‘女’,’1996-10-3’)
或
INSERT
into ST VALUES(‘150112’,‘130212199707120895’,‘张强’,‘网络工程’,‘男’,‘1997-7-12’,150,‘2010-9-1’)
(1).例:在STUDENT1数据库的学生(ST)表中的“性别”字段的值设为“男”。
USE STUDENT1
GO
UPDATE
ST
SET 性别=‘男’
(2). USE STUDENT1
GO
UPDATE ST
SET 性别=‘女’
WHERE 姓名=‘杨丽’
(3). 例:在STUDENT1数据库的学生表中添加一字段“备注”nvarchar(20);“备注”字段信息为’已毕业’ 。
①USE STUDENT1
GO
ALTER TABLE ST
Add 备注
nvarchar(20)
②UPDATE ST
SET 备注=‘已毕业’
(4). 例:在学生表中,将学号为‘150112’的学生姓名改为“王武”。
USE STUDENT1
GO
UPDATE ST
SET 姓名=‘王武’
WHERE 学号=‘150112’
(1)例:删除学生表中,将学号为‘150112’的学生记录删除。
USE STUDENT1
DELETE
FROM ST
WHERE 学号 = ‘150112’
(2)使用TRUNCATE TABLE清空表数据
语法格式:TRUNCATE TABLE table_name
TRUNCATE TABLE与不含有WHERE子句的DELETE语句在功能上相同。但是,TRUNCATE
TABLE速度更快,其使用更少的系统资源和事务日志资源。
例:清空学生表中的数据
TRUNCATE TABLE
ST
SQL Server 2008中的MERGE语句能做很多事情,它的功能是根据源表对目标表执行插入、更新或删除操作。
最典型的应用就是进行两个表的同步。
假设数据库中有两个表:产品表“Product”和新产品表“ProductNew”。
源表:Product
CREATE TABLE Product
( ProductID char(7) PRIMARY KEY, --产品编号
ProductName nvarchar(30) NOT NULL, --名称
Price decimal(13,2) DEFAULT
0 ) --价格INSERT INTO Product
Values (‘4100037’,‘优盘’,50), (‘4100038’,‘鼠标’,30)
目标表:ProductNew
CREATE TABLE ProductNew
(ProductID char(7) PRIMARY KEY,
ProductName nvarchar(30) NOT NULL,
Price decimal(13,2) DEFAULT
0 )
MERGE ProductNew d USING Product s
ON s.ProductID = d.ProductID
WHEN NOT MATCHED THEN INSERT(
ProductID,ProductName,Price)
VALUES(s.ProductID,s.ProductName,s.Price);
注意:源表可以是表,也可以是一个子查询语句。格外强调一点,MERGE语句最后的分号是不能省略的!
修改单价:UPDATE Product SET Price=55 WHERE ProductID= ‘4100037’
插入和修改都同步:
MERGE ProductNew d USING Product s
ON s.ProductID = d.ProductId
WHEN NOT MATCHED THEN INSERT(
ProductID,ProductName,Price)
VALUES(s.ProductID,s.ProductName,s.Price)
WHEN MATCHED THEN
UPDATE SET d.ProductName = s.ProductName,
d.Price = s.Price;
删除数据:DELETE Product WHERE ProductID= ‘4100037’
插入、修改和删除都同步:
MERGE ProductNew d USING
Product s
ON s.ProductID=d.ProductId
WHEN NOT MATCHED BY TARGET
THEN INSERT(ProductID,ProductName,Price)
VALUES(s.ProductID,s.ProductName,s.Price)
WHEN NOT MATCHED BY SOURCE
THEN DELETE
WHEN MATCHED THEN
UPDATE SET d.ProductName = s.ProductName,
d.Price = s.Price;
删除表就是将表中数据和表的结构从数据库中永久性地去除。表被删除之后,就不能再恢复该表的定义。
例: 删除学生表(ST)
DROP
TABLE ST
【例1】查询 “teaching”数据库中学生的姓名、性别和专业。
USE
teaching
SELECT
sname, ssex, specialty FROM student
【例2】查询
“teaching”库中“course”的所有记录。
USE
teaching
SELECT
注:用“*”可以表示表中所有的列。
【例3】查询
“teaching”中“学生表”的专业名称,滤掉重复行。
USE
teaching
SELECT
DISTINCT specialty
FROM student
用DISTINCT关键字可以过滤掉查询结果中的重复行。
【例4】查询“teaching”库中“course”表的前三行信息。
USE
teaching
SELECT
top 3 * FROM course
【例5】查询“teaching”库中“course”表的前50%行的信息。
USE
teaching
SELECT
top 50 percent * FROM course
修改查询结果中的列标题(显示标题)——起别名
【例6】查询“student”表中所有学生的学号、姓名,结果中各列的标题分别指定为汉字学号和姓名。
USE
teaching
SELECT sno AS 学号, sname AS 姓名
FROM student
或:
USE
teaching
SELECT
sno 学号, sname 姓名
FROM student
或:
USE
teaching
SELECT 学号=sno, 姓名=sname
FROM student
计算列值
【例7】查询“SC”表,按150分制计算成绩。
USE
teaching
SELECT
sno, cno, score150=score*1.50
FROM sc
【例1】查询“teaching”库“sc”表中成绩大于等于60的学生的学号、课程号和成绩。
USE
teaching
SELECT * FROM sc
WHERE score>=60(关系表达式)
【例2】查询“teaching”库中“计算机”专业的“男”生的信息。(多条件的逻辑表达式)
USE
teaching
SELECT * FROM student
WHERE specialty=‘计算机’ and
ssex=‘男’
【例3】查询“teaching”库中“计算机”专业的或“男”生的信息。
USE
teaching
SELECT * FROM student
WHERE specialty=‘计算机’ or ssex=‘男’
【例4】查询“teaching”库中成绩在80到90之间的学生的学号、课程号和成绩。
USE
teaching
SELECT * FROM sc
WHERE score BETWEEN 80 AND 90
或:
USE
teaching
SELECT * FROM sc
WHERE score>= 80 AND score<=90
【例5】查询“teaching”库中”计算机”和”网络”专业的学生的姓名、学号和专业。
USE
teaching
SELECT sname,sno,specialty
FROM student
WHERE specialty IN(‘计算机’ ,‘网络’)
使用[NOT] LIKE关键字(模糊查找):LIKE关键字搜索与指定模式匹配的字符串、日期或时间值。模式包含要搜索的字符串,字符串中可包含4种通配符的任意组合。
【例6】通配符的示例
LIKE ‘AB%’
返回以“AB”开始的任意字符串。
LIKE ‘%abc’
返回以“abc”结束的任意字符串。
LIKE ‘%abc%’
返回包含“abc”的任意字符串。
LIKE ‘_ab’
返回以“ab”结束的三个字符的字符串。
LIKE ’ [ACK]% ’
返回以“A”、“C”或“K”开始的任意字符串。
LIKE ’ [A-T]ing’
返回四个字符的字符串,结尾是“ing”,首字符的范围从A到T。
LIKE 'M[^c]% ’
返回以“M”开始且第二个字符不是“c”的任意长度的字符串。
【例7】查询“teaching”库中所有姓“张”的学生的信息。
USE teaching
SELECT * FROM student
WHERE sname like ‘张%’
【例8】查询“teaching”库中所有“成绩”为空的学生的学号、课程号和成绩。
USE teaching
SELECT * FROM sc
WHERE score IS NULL
复合条件查询的优先级问题:
【例9】从“teaching”库的“student”表中查询所有“计算机”和“通信”专业的“女”生的信息。
USE teaching
SELECT * FROM student
WHERE ssex=‘女’ AND
(specialty=‘计算机’
OR specialty=‘通信’)
聚合函数可以实现数据集合的汇总或是求平均值等各种运算。
【例1】在“teaching”库中查询“sc”表中成绩的平均值,平均值显示列标题为“平均成绩”。
USE
teaching
SELECT avg(score) AS 平均成绩
FROM
sc
【例2】查询学生的人数。
USE
teaching
SELECT count(*) AS 学生人数
FROM student
【例3】查询专业的种类(相同的按一种计算)。
USE
teaching
SELECT count (DISTINCT specialty)
AS 专业种类数 FROM student
【例4】在“teaching”库中查询1302001号学生的平均成绩。
USE
teaching
SELECT avg(score) AS 平均成绩
FROM sc
WHERE sno= ‘1302001’
没有使用CUBE或ROLLUP关键字的分组技术。
【例1】查询“teaching”库中男生和女生的人数。
USE
teaching
SELECT ssex, count(ssex) 人数
FROM student
GROUP BY ssex
HAVING关键字可以对查询和统计的结果进行进一步的筛选
【例2】在“sc”表中查询选修了两门及以上课程的学生学号和选课数。
USE
teaching
SELECT sno,COUNT(cno) 选修课程数 FROM sc
GROUP BY sno
HAVING COUNT(cno)>=2
【例3】在“teaching”库中查询“sc”表,求被选修的各门课程的平均成绩和选修该课程的人数,及所有课程的总平均成绩和总选修人数。
USE teaching
SELECT cno, AVG(score) AS ‘平均成绩’,COUNT(sno)
AS ‘选修人数’
FROM sc
GROUP BY cno
WITH CUBE
【例4】在“teaching”库中查询“student”表,统计各专业男生、女生人数及每个专业的学生人数和男生总人数、女生总人数以及所有学生总人数。
USE teaching
SELECT specialty,ssex,COUNT(*) AS ‘人数’
FROM student
GROUP BY specialty,ssex
WITH CUBE
【例5】统计在“teaching”库中每个专业的男女生人数,每个专业的总人数和所有学生总人数。
USE teaching
SELECT specialty,ssex,COUNT(*) AS ‘人数’ FROM student
GROUP BY specialty,ssex
WITH ROLLUP
【例1】在“teaching”中查询“计算机”专业的学生的学号、姓名和性别,并统计学生总人数。
USE teaching
SELECT sno,sname,ssex
FROM student
WHERE specialty= ‘计算机’
COMPUTE COUNT(sno)
【例2】在“teaching”库中查询所有学生的选课信息,并计算每个学生的平均成绩。
USE teaching
SELECT sno,cno,score
FROM sc
ORDER BY sno
COMPUTE avg(score) BY sno
【例1】
从“teaching”库中查询每个学生的姓名、课程号和成绩。
USE teaching
SELECT student.sname, sc.cno, sc.score
FROM student INNER JOIN sc ON student.sno=sc.sno
也可以利用下面的语句来实现:
SELECT student.sname, sc.cno, sc.score
FROM student,sc
WHERE
student.sno=sc.sno
注意:在列名不同时,列名前可以不加表名,但有时也会加上表名,以增强可读性。
【例2】
从“teaching”库中查询“计算机”专业的学生所选课程的平均分。
USE teaching
SELECT b.cno, avg(b.score) as 平均分
FROM student a INNER JOIN sc b
ON a.sno=b.sno and a.specialty=‘计算机’
GROUP BY b.cno
注:为了简化输入,可以在查询中使用别名,以缩写表名;可以在FROM子句中为表定义一个临时别名,在查询中引用。
带筛选条件的三个表的内连接:查询成绩在75分以上的学生的学号、姓名,选修课的课程号、课程名、成绩。
USE teaching
SELECT C.cno, C.cname, A.sno, A.sname,
B.score FROM student AS A JOIN SC AS B
ON A.sno=B.sno AND B.score>75
JOIN course AS C on B.cno=C.cno
(或where B.score>75 放在最后)
连接操作也可以在同一张表内进行自身连接,即将同一个表的不同行连接起来。
自连接必须为表指定两个别名,使之在逻辑上成为两张表。
【例8-3】从“teaching”库中查询同名学生的信息。
USE teaching
SELECT * FROM student a INNER JOIN student b ON a.sname=b.sname AND a.sno<>b.sno
(1)外连接分为3种类型
左外连接:对连接条件中左边的表不加限制;
右外连接:对右边的表不加限制;
全外连接: 对两个表都不加限制,所有两个表中的行都会包括在结果集中。
【例1】在“teaching”库中查询每个学生及其选修课程的成绩情况(含未选课的学生信息)。
USE teaching
SELECT student.*,sc.cno,sc.score
FROM student LEFT JOIN sc
ON student.sno=sc.sno
【例2】在”teaching”库中查询每个学生及其选修课程的情况(含未选课的学生信息及未被选修的课程信息)。
USE teaching
SELECT course.*,sc.score,student.sname,
student.sno
FROM course FULL JOIN sc
ON course.cno=sc.cno FULL JOIN student
ON student.sno=sc.sno
[例3]查询所有男生的选课信息,包括没选课的男生。
USE 教学库
SELECT student.*,sc.cno,sc.score
FROM student LEFT JOIN sc
ON student.sno=sc.sno and ssex=‘男’
或where ssex=‘男’
USE teaching
SELECT sno, sname, specialty
FROM student
WHERE specialty=
(SELECT specialty
FROM student
WHERE sname=‘沈艳’)
【例2】在“teaching”库中查询C001号课的考试成绩比“郑丽”高的学生的学号和姓名。
USE teaching
SELECT student.sno,sname
FROM student,sc
WHERE student.sno = sc.sno and cno=‘C001’
and score>(SELECT score FROM sc WHERE
cno=‘C001’ and sno=(SELECT sno FROM
student WHERE sname=‘郑丽’))
2) SOME、ANY、ALL和IN子查询
能确切知道子查询返回的是单值时,可以用>,<,=,>=,<=,!=或<>等比较运算符。
【例3】查询计算机专业年龄最大的学生的学号和姓名。
USE teaching
SELECT sno,sname FROM student WHERE
sage>= ALL
(SELECT sage FROM student WHERE specialty=‘计算机’) AND specialty=‘计算机’
【例4】在“teaching”库中查询选修了“C001”号课程的学生姓名和所在专业。
USE teaching
SELECT sname,specialty
FROM student
WHERE sno IN
(SELECT sno FROM sc
WHERE cno=‘C001’)
3)子查询结果作为主查询的查询对象
【例5】在“teaching”库中查询有2个以上学生平均成绩超过80分的班级(用年级和专业表示)。
USE teaching
SELECT grade,specialty FROM student s,
(SELECT sno FROM SC GROUP BY sno
HAVING AVG(score) >=80) ss
WHERE s.sno=ss.sno
GROUP BY grade,specialty
HAVING COUNT(*)>=2
或
USE teaching
SELECT grade,specialty FROM student
WHERE sno IN (SELECT sno FROM SC GROUP BY
sno
HAVING AVG(score) >=80)
GROUP BY grade,specialty
HAVING COUNT(*)>=2
1)比较子查询
【例6】在“teaching”库中查询成绩比该课的平均成绩低的学生的学号、课程号、成绩。
USE teaching
SELECT sno,cno,score
FROM
sc a
WHERE score<( SELECT avg(score) FROM sc b
WHERE b.cno=a.cno)
【例7】在“teaching”库中查询有2门以上课程的成绩在80分以上的学生的学号、姓名、年级和专业。
SELECT sno,sname,grade,specialty
FROM student s
WHERE (SELECT COUNT(*) FROM sc
WHERE sc.sno=s.sno
and score >=80)>=2
注:EXISTS子查询的目标属性列表达式一般用*表示,因为带EXISTS的子查询只返回真或假值,给出列名无实际意义。
【例8】在“teaching”库中查询所有选修了C004号课程的学生姓名。
USE teaching
SELECT sname FROM student
WHERE EXISTS (SELECT * FROM sc
WHERE sno=student.sno AND cno= ‘C004’)
【例1】查询选修了课程C001或课程C004的学生的姓名。
USE teaching
SELECT sname FROM sc,student
WHERE cno=‘C001’ and sc.sno=student.sno
UNION
SELECT sname FROM sc,student
WHERE cno=‘C004’ and sc. sno=student.sno
又例:查询所有学生的学号、姓名和所有教师编号、姓名。
EXCEPT(差)和INTERSECT查询(交)
【例2】查询没有选课的学生的学号。
SELECT sno FROM student
EXCEPT
SELECT sno FROM sc
【例3】查询选了既选修了C001又选修了C004课程的学生的学号。
SELECT sno FROM sc WHERE cno=‘C001’
INTERSECT
SELECT sno FROM sc WHERE cno=‘C004’
【例4】查询“teaching”库中“女”学生的姓名和专业,并按姓名升序排列。
USE
teaching
SELECT sname,specialty
FROM student
WHERE ssex=’女’
ORDER BY sname ASC
【例5】查询“sc”中学生的成绩和学号,并按成绩(降序)排列,若成绩相同按学号(升序)排列。
USE
teaching
SELECT sno,score FROM sc
ORDER BY score DESC,sno ASC
【例6】使用TOP关键字查询“course”表中“学分”最高的前两门课。
USE
teaching
SELECT
TOP 2 cname,credit
FROM course
ORDER BY credit DESC
3 22. 存储查询结果
【例7】查询的学生姓名、学号、课程名、成绩的相关数据存放在表“成绩单”中。
USE teaching
SELECT sname,student.sno, cname, score
INTO 成绩单 FROM
student,sc,course
WHERE student.sno=sc.sno
AND course.cno=sc.cno
【例1】在“teaching”库中创建“sc”表的一个副本“成绩表”,将“sc”中成绩大于80的数据添加到“成绩表”中,并显示表中内容。
USE teaching
GO
CREATE TABLE 成绩表
(学号 char(7),
课程号 char(4) ,
成绩 int )
GO
INSERT INTO 成绩表(学号,课程号,成绩)
SELECT * FROM sc
WHERE score>=80
GO
SELECT * FROM 成绩表
【例2】将13级计算机专业张明明选修的“C001”号课的成绩改为92分。
方法一:使用SELECT子句
UPDATE sc SET score=92
WHERE cno=‘C001’ AND sno=
(SELECT sno FROM student
WHERE sname=‘张明明’ AND grade=‘13级’
AND specialty=‘计算机’)
方法二:使用JOIN内连接
UPDATE sc SET score=92 FROM sc
JOIN student ON student.sno=sc.sno
WHERE cno=‘C001’ AND
sname=‘张明明’ AND grade=‘13级’
AND specialty=‘计算机’
【例3】在“teaching”库中将13级计算机专业张明明选修的C001号课删除。
方法一:使用SELECT子句
DELETE sc WHERE cno=‘C001’
AND sno=
(SELECT sno FROM student
WHERE sname=‘张明明’ AND grade=‘13级’
AND specialty=‘计算机’)
方法二:使用JOIN内连接
DELETE sc FROM sc
JOIN student ON student.sno=sc.sno
WHERE cno=‘C001’ AND
sname=‘张明明’ AND grade=‘13级’
AND
specialty=‘计算机’
[例1]创建视图s_c_sc ,包括地理信息专业的学生的学号、姓名,和他们选修的课程号、课程名和成绩。
USE teaching
GO
CREATE VIEW s_c_sc
AS
SELECT
student.sno,sname,course.cno,cname,score
FROM student,sc,course WHERE
student.sno=sc.sno
AND course.cno=sc.cno AND sdept=‘地理信息’
GO
[例2]创建库存统计视图inve_count
,求每种商品的总库存数量,要求包括商品编号和商品名称。
USE inventory
GO
CREATE VIEW inve_count
AS
SELECT goods.gno,gname,SUM(number) AS
snumber
FROM goods,invent
WHERE goods.gno= invent.gno
GROUP BY goods.gno,gname
GO
[例3]修改库存统计视图inve_count
,求每种商品的总库存数量和所在仓库的个数
,要求包括商品编号和商品名称。
ALTER VIEW inve_count
AS
SELECT goods.gno,gname,SUM(number) AS
snumber, COUNT(stno) AS storenum
FROM goods,invent
WHERE goods.gno= invent.gno
GROUP BY goods.gno,gname
GO
【例4】在视图上创建视图:创建“goodscount”商品统计视图,求每种商品的总库存数量和和总价值,要求包括商品编号和商品名称。
USE inventory
GO
CREATE VIEW goodscount
AS
SELECT goods.gno, goods.gname, snumber,
snumber *price as sumprice
FROM goods, inve_count
WHERE goods.gno= inve_count .gno
GO
【例1】在查询窗口中查询s_c_sc视图,统计“C++语言”课程的总分和平均分。
USE teaching
SELECT sumscore=SUM(score),
avgscore=AVG(score) FROM s_c_sc
WHERE cname=‘C++语言’
【例2】查询“inve_count”视图中“冰箱”的商品统计信息。
USE inventory
SELECT * FROM inve_count
WHERE gname=‘冰箱’
使用视图修改基本表中数据
修改视图的数据,其实就是对基本表进行修改,因为真正存放数据的地方是基本表而不是视图。
同样使用INSERT、UPDATE、DELETE语句来完成数据的插入、修改和删除。
注意:并不是所有的视图都可以更新数据,只有对满足可更新条件的视图才能更新数据。
可更新条件*:
(1)任何通过视图的数据修改(包括UPDATE、INSERT和DELETE语句)都只能引用一个基本表的列。
①如果视图数据为一个表的行、列子集,则此视图可更新(包括UPDATE、INSERT和DELETE语句);但如果视图中没有包含表中某个不允许取空值又没有默认值约束的列,则不能利用视图插入数据。
②如果视图所依赖的基本表有多个时,完全不能向该视图添加(INSERT)数据。
③若视图依赖于多个基本表,那么一次修改只能修改(UPDATE)一个基本表中的数据。
④若视图依赖于多个基本表,那么不能通过视图删除(DELETE)数据。
(2)视图中被修改的列必须直接引用表列中的基础数据。不能是通过任何其他方式对这些列进行派生而来的数据,比如通过聚合函数、计算(如表达式计算)、集合运算等。
(3)被修改的列不应是在创建视图时受GROUP
BY、HAVING、DISTINCT或TOP子句影响的。
【例3】通过“male_view”视图向“student”表中插入一个“男”生。
INSERT INTO male_view VALUES (‘1501005’, ‘张三’, ‘男’, 19)
如果通过“male_view”视图向“student”表中插入一个“女”生,也可以完成.
如果不希望用户通过“male_view”视图插入“女”生,在创建“male_view”视图时应该使用WITH CHECK OPTION选项。
命令如下:
CREATE VIEW male_view AS
SELECT sno, sname, ssex, sage, en_time,
specialty, grade
FROM student WHERE ssex = ‘男’
WITH CHECK OPTION
【例】删除前面例子创建的s_c_sc视图。
USE teaching
GO
DROP VIEW s_c_sc
GO
[例1] 根据教学库中学生表的姓名列的升序创建一个名为index_sname的普通索引。
USE 教学库
GO
CREATE INDEX index_sname
ON student(sname)
GO
[例2] 根据仓库库存数据库中商品表的商品名称、生产商创建一个名为商品_生产商的唯一性复合索引,其中商品名称为升序,生产商为降序。
USE 仓库库存
GO
CREATE UNIQUE INDEX gname_pro
ON goods(gname ASC, producer DESC)
GO
间接创建索引
在定义表结构或修改表结构时,如果定义了主键约束(PRAMARY KEY)或者唯一性约束(UNIQUE),可以间接创建索引。
[例3] 创建一个s1表,并定义了主键约束。
USE teaching
GO
CREATE TABLE s1(
sno
char(6) PRIMARY KEY,
sname char(8) )
此例中,就按sno升序创建了一个聚集索引。
[例4] 创建一个教师表,并定义了主键约束和唯一性约束。
USE teaching
GO
CREATE TABLE teacher(
tno
char(6) PRIMARY KEY,
tname char(8) UNIQUE )
此例中,创建了两个索引,按tno升序创建了一个聚集索引,按tname升序创建了一个非聚集唯一索引。
视图必须满足下列要求才可以创建索引:
(1)当执行 CREATE VIEW 语句时,ANSI_NULLS
和 QUOTED_IDENTIFIER 选项必须设置为 ON。
(2) 创建视图引用的表时,ANSI_NULLS 选项必须设置为 ON。
(3)视图不能引用任何其它视图,只能引用基本表。
(4)视图引用的所有基本表必须与视图位于同一个数据库中,并且所有者也与视图相同。
(5)必须使用 SCHEMABINDING 选项创建视图。
(6)必须已使用 SCHEMABINDING 选项创建了视图中引用的用户定义的函数。
(7)表和用户定义的函数必须由两部分的名称引用。
(8)视图中的表达式所引用的所有函数必须是确定性的。
(9)选择列表不能使用 * 或
table_name.* 语法指定列。必须显式给出列名。
【例】创建一个“female_view”女生视图,并为该视图按“sno”升序创建一个具有唯一性的聚集索引。
创建视图:
CREATE VIEW female_view WITH SCHEMABINDING
AS
SELECT sno,sname,ssex,specialty FROM
dbo.student
WHERE ssex= ‘女’
创建索引:
CREATE UNIQUE CLUSTERED INDEX index_female
ON female_view(sno)
使用T-SQL语句查看索引信息
可以使用系统存储过程sp_help index或sp_help来查看索引信息
(1) 使用系统存储过程sp_helpindex查看索引基本信息
EXEC
sp_helpindex student
(2) 使用系统存储过程sp_help查看索引及其他信息
EXEC
sp_help student
当一个索引不再需要时,可以将其从数据库中删除,以释放占用的存储空间。
注意**:(1)必须删除约束,才能删除PRIMARY KEY或UNIQUE约束使用的索引。
(2)删除某个表时,会自动删除在此表上创建的索引。
[例]删除学生表中的“Index_sname”索引。
USE teaching
GO
DROP
INDEX student.Index_sname
GO