SQL语句综合总结(详解)


注: 此处跳转到习题总练习

一、数据定义

1、数据库的定义

1. 数据库的创建

//注:接下来模板中的[ ]表示非必要语句.

  • 模板
CREATE DATABASE <数据库名>
[ON [PRIMARY][(NAME=<逻辑数据文件名>]
 FILENAME=<操作数据文件路径和文件名>[,SIZE=<文件长度>]
 [,MAXSIZE=<最大长度>]
 [,FILEGROWTH=<文件增长率>] ) [,…n]]
[LOG ON ([NAME= <逻辑日志文件名>]
FILENAME=<操作日志文件路径和文件名>[,SIZE= <文件长度>]
[,MAXSIZE=<最大长度>] [,…n]]
 [FOR RESTORE] 
  • 举例

建立一个学生选课表 S_C,并将数据库文件放在指定位置。

CREATE  DATABASE S_C
ON PRIMARY(   
	NAME='s_c_data',						/*逻辑数据文件名,注意格式一般_data结尾*/
	FILENAME='D:\Retro_sql\s_c_data.mdf'	/*操作数据文件路径和文件名,注意格式一般data.mdf结尾(primary data file)*/
	--,SIZE=   ,MAXSIZE=                  /*文件长度等等其他操作*/
)
LOG ON(
	NAME='s_c_log',							/*逻辑日志文件名,注意格式一般_log结尾*/
	FILENAME='D:\Retro_sql\s_c_log.ldf'		/*操作日志文件路径和文件名,注意格式一般log.ldf结尾(Log data files)*/
)


/*exec sp_helpdb  S_C  此代码可以查看数据库信息*/

该数据库信息查询如下:
在这里插入图片描述

2. 数据库的使用和删除

  • 模板
USE〈数据库名〉           /*使用数据库*/ 

DROP DATABASE <数据库名>  /*删除数据库*/
  • 举例
USE S_C             /*使用数据库*/ 

DROP DATABASE S_C   /*删除数据库*/

2、表的定义

  • 模板
CREATE TABLE <表名>
(< 列 名 >< 数 据 数 型 >[< 列 级 完 整 性 约 束 条 件 >]
[,……n] [,<表级完整性约束>]); 

  *如果约束条件涉及多个属性列,则必须定义为表级完整性约束。

  *如果约束条件只是涉及一个属性列,则既可以定义在表级完整性约束,也可以定义在列级,

  *接下来做举例:

  • 举例

例子一:建表,设置主键、唯一键、not null 约束 和其他自定义约束,设置默认值。

/* 建学生表 */
/*建表语句一:列级完整性约束写法*/
CREATE TABLE Student
(
Sno CHAR(10) PRIMARY KEY,         /*列级完整性约束,主键*/
Sname CHAR(20) NOT NULL UNIQUE,   /*列级完整性约束,不可为空且唯一*/
Ssex CHAR(2) NOT NULL,            /*如果不加 NOT NULL,默认可以为NULL*/
Sage SMALLINT NOT NULL,
Sdept CHAR(20) NOT NULL
);

/*建表语句二:表级约束写法*/

CREATE TABLE Student
(
Sno CHAR(10),
Sname CHAR(20),
Ssex CHAR(2) NOT NULL,
Sage SMALLINT,
Sdept CHAR(20) ,
CONSTRAINT SnoKey PRIMARY KEY(Sno),/*定义在表级完整性*/
UNIQUE (Sname)                     /*定义在表级完整性*/
);

/* 建表语句三:统一表级定义键与自定义约束,并加上默认值 */
/* 一般我习惯这么写,既能清晰统一,还能自定义约束名,不过默认值为了方便就直接接上了 */
CREATE TABLE Student
(
	Sno CHAR(10) NOT NULL,
	Sname CHAR(20) NOT NULL,
	Ssex CHAR(2) NOT NULL,
	Sage SMALLINT NOT NULL DEFAULT (18),            /* 设置默认值 */
	Sdept CHAR(20) NOT NULL DEFAULT ('计算机学院'),
	
	CONSTRAINT SsexKey CHECK (Ssex IN ('男','女')), /* 性别只能为男or女 */
	CONSTRAINT SageKey CHECK (Sage > 0),			/* 年龄>0 */
	CONSTRAINT SnoKey PRIMARY KEY(Sno),				/* 设置主键 */
	CONSTRAINT UqSname UNIQUE (Sname)				/* 设置唯一键 */
);

/* 同理建课程表 */
CREATE TABLE Course
(
	Cno CHAR(10) NOT NULL,
	Cname CHAR(16) NOT NULL,
	Ccredit SMALLINT NOT NULL,
	Cpno CHAR(3) NULL,
	CONSTRAINT CnoKey PRIMARY KEY(Cno)
); 

  这里可以看到一个区别,就是第二个建表语句主键加了 “CONSTRAINT SnoKey” 语句后可以自定键名,由下图可以观察到区别:
在这里插入图片描述
例子二:建表,设置多属性主键、外键

CREATE TABLE Sc
(
	Sno CHAR(10) NOT NULL,
	Cno CHAR(10) NOT NULL,
	Grade SMALLINT NULL,
	CONSTRAINT ck_Grade CHECK ( Grade<= 100),
	CONSTRAINT SCnoKey PRIMARY KEY(Sno,Cno),/* 多属性主键设置 */
	CONSTRAINT fk_Sno  FOREIGN KEY(Sno) REFERENCES Student(Sno), /* 外键键设置 */
	CONSTRAINT fk_Cno  FOREIGN KEY(Cno) REFERENCES Course(Cno)
);

3、表的修改

  • 模板
  ALTER TABLE <表名 > --注意ALTER表时不需要加括号,与CREATE不同
 [ ADD <新列名> <数据类型> [完整性约束] ]
 [ ADD [CONSTRAINT <约束名>] <完整性约束>]
 [ DROP  <完整性约束> ]
 [ DROP COLUMN< 列名> ]
 [ ALTER COLUMN <列名><数据类型>]
  • 举例

例一:添加列

/* (1)添加列 */
/* 添加一列,学生表增加专业,默认为“计算机科学与技术”*/
ALTER TABLE Student
ADD Smajor CHAR(20) DEFAULT('计算机科学与技术') 

例二:删除列

/* (2)删除列 */
/* 删除学生表专业列*/
ALTER TABLE Student
DROP COLUMN Smajor

例三:更改列

/* (3)更改列 */
/* 修改选课表的'GRADE'字段为INT;(列上存在约束时可能无法修改)*/
ALTER TABLE Sc
ALTER COLUMN Grade INT

例四:添加完整性约束

/* (4)添加实体完整性 */
/* 为学生表添加主键约束 */
ALTER TABLE Student
ADD CONSTRAINT PK_Sno PRIMARY KEY(Sno)
/* 为选课表添加主键约束 */
ALTER TABLE Sc
ADD CONSTRAINT SCnoKey PRIMARY KEY(Sno,Cno)

/* (5)添加参照完整性 */
/* 为选课表添加外键约束 */
ALTER TABLE Sc
ADD	CONSTRAINT fk_Sno  FOREIGN KEY(Sno) REFERENCES Student(Sno) 
ALTER TABLE Sc
ADD	CONSTRAINT fk_Cno  FOREIGN KEY(Cno) REFERENCES Course(Cno)

/* (6)添加用户自定义完整性 */
/* 为一列增加约束,约束学生表性别只能为男or女 */
ALTER TABLE Student
ADD CONSTRAINT CK_Ssex CHECK(Ssex IN ('男','女'))
/* 为一列增加约束,约束学生表年龄>0 */
ALTER TABLE Student
ADD CONSTRAINT CK_Sage CHECK(Sage > 0) 
/* 为一列增加默认,默认学生表专业为“计算机科学与技术” */
ALTER TABLE Student
ADD CONSTRAINT DF_Smajor DEFAULT('计算机科学与技术') FOR Smajor 

例五:删除完整性约束

/* (7)删除完整性约束 */
/*  删除选课表主键SCnoKey */
ALTER TABLE Sc
DROP SCnoKey

4、表的删除

  • 模板
DROP TABLE <表名> [RESTRICT|CASCADE];
--RESTRICT会考虑到约束、依赖等关系,默认为RESTRICT
--但CASCADE会不考虑而全都删除(比如视图)

二、数据查询

–此处参考数据查询习题集–

  • 模板
SELECT [ALL|DISTINCT] <目标列名> [,<目标列名>...]
FROM <表名或视图名> [,<表名或视图名>...]  
WHERE <条件表达式>                     --查询条件
GROUP BY <列名1> [HAVING <条件表达式>] --分组
ORDER BY <列名1> [ASC|DESC]  --排序,升序|降序

注:这里很多时候会用到GROUP BY 和 ORDER BY语句,这里就不多赘述了,可以从具体例子中体会

0、查询条件语句和聚集函数

  • 上述模板中WHERER子句一般有如下常用常用查询条件语句
  1. 比较:< , > , = , <> 等;
  2. 确定范围:[NOT] BETWEEN AND;
  3. 确定集合:[NOT] IN;
  4. 字符匹配:[NOT] LIKE;
  5. 空值判断:IS [NOT] NULL;
  6. 多重条件:AND , OR , NOT
  • 其中SELECTGROUP BY 的 HAVING 可以用聚集函数(WHERE不行)
  1. COUNT(*):统计元组数量;
  2. COUNT([DISTINCT|ALL] <列名>):统计一列中值的个数;
  3. SUM([DISTINCT|ALL] <列名>) 计算一列中值的总和;
  4. AVG([DISTINCT|ALL] <列名>) 计算一列中值的平均值;
  5. MAX([DISTINCT|ALL] <列名>) 计算一列中值的最大值;
  6. MIN([DISTINCT|ALL] <列名>) 计算一列中值的最小值;

注:聚集函数里也可以加上条件,如:

SELECT COUNT(CASE WHEN 选课.Grade>80 THEN 1 ELSE NULL END) 成绩大于80的人数

1、单表查询

  • 单表查询,顾名思义也就是在一个表内查询,是最简单的查询方式,对应最简单的需求。

  • 举例

例一:查询数学系男学生的学号和姓名;

SELECT Sno,Sname
FROM Student
WHERE Sdent='数学学院' AND
	  Ssex='男';

2、连接查询

  • 连接查询需要多表的数据,一般将多表连接起来后根据查询条件完成查询。
(1)一般连接
  • 举例

例一:查询选修了1号课程的学生学号

SELECT Sc.Sno
FROM Student,Sc
WHERE Student.Sno=Sc.Sno AND
	  Sc.Cno='001';

例二:查询成绩在80~90分之间的学生学号和成绩

SELECT Sc.Sno,Sc.Grade
FROM Student,Sc
WHERE Student.Sno=Sc.Sno AND
	  Sc.Grade BETWEEN 80 AND 90;

例三:查询选修了1号课程且成绩在80~90分之间的学生学号和成绩,并将成绩乘以系数0.8输出

SELECT Sc.Sno,0.8*Sc.Grade 折算成绩
FROM Student,Sc
WHERE Student.Sno=Sc.Sno AND
	  Sc.Cno='001' AND
	  Sc.Grade BETWEEN 80 AND 90;

例四:查询数学系或计算机系姓张的学生的信息

SELECT *
FROM Student
WHERE (Sdent='数学学院' OR
	  Sdent='计算机学院') AND 
	  Sname LIKE '张%'; --%表示任意长度,_表示单个字符,由于无法确认名长度,所以用%
(2)连接+排序
  • 举例

例一:查询选修了1号课程的学生学号和成绩,并要求结果按成绩降序排列

SELECT Sc.Sno,Sc.Grade
FROM Student,Sc
WHERE Student.Sno=Sc.Sno AND
	  Sc.Cno='001'
ORDER BY Grade DESC;

例一:查询选修了1号课程的学生学号和成绩,并要求结果按成绩降序排列,如果成绩相同,则按学号升序排列

SELECT Sc.Sno,Sc.Grade
FROM Student,Sc
WHERE Student.Sno=Sc.Sno AND
	  Sc.Cno='001'
ORDER BY Grade DESC , Sc.Sno ASC;
(3)外连接

例一:查询学生的学号、姓名、选修的课程名称及成绩;(要求:没有选课的也查出来)

SELECT Student.Sno,Sname,Cname,Grade
FROM Student 
LEFT OUTER JOIN Sc 
ON Student.Sno=Sc.Sno 
LEFT OUTER JOIN Course 
ON Sc.Cno=Course.Cno;

3、嵌套查询

  • 除了连接查询,嵌套查询也是非常实用的查询语句。
  • 嵌套时的子查询有谓词ANY 和 ALL,如WHERE Grade> ALL(…),记得注意这俩个区别。
  • 同时谓词EXIST也是一个小难点,使用WHERE EXIST(…)后,如果子查询未查到值,就直接返回false,否则相反;NOT EXIST同理。下面进阶嵌套里有具体例子。
(1)基础嵌套

例一: 查询选修了“高等数学”的学生学号和姓名

SELECT Sno,Sname
FROM Student
WHERE Sno IN
		 (SELECT Sno
		  FROM Sc
		  WHERE Cno IN
				   (SELECT Cno
				    FROM Course
					WHERE Cname='高等数学'))
					

例二: 查询其他系中年龄小于计算机系年龄最大者的学生

SELECT *
FROM Student
WHERE Sdent<>'计算机学院' AND
		Sage<
			(SELECT MAX(Sage)
			FROM Student
			WHERE Sdent='计算机学院');

例三: 查询其他系中比计算机系学生年龄都小的学生

SELECT *
FROM Student
WHERE Sdent<>'计算机学院' AND
		Sage<ALL
			(SELECT Sage
			FROM Student
			WHERE Sdent='计算机学院');

(2)进阶嵌套(EXISITS)

例一: 查询没有选修“信息系统”课程的学生姓名

SELECT Sname
FROM Student
WHERE NOT EXISTS
		 (SELECT Sno
		  FROM Sc
		  WHERE Sc.Sno=Student.Sno AND
					Sc.Cno IN
				   (SELECT Cno
				    FROM Course
					WHERE Cname='信息系统'
					));

例二:查询选修了全部课程的学生姓名

这种需求我们可以这么理解:当我们要查询选修了所有课程的学生,那么对于其中一个学生来说,没有一门课是他没选的,这样就巧妙地将全称量词转化为了存在量词,即EXISTS。


SELECT Sname
FROM Student
WHERE NOT EXISTS
     (SELECT *
	  FROM Course
	  WHERE NOT EXISTS
	       (SELECT *
		    FROM Sc
			WHERE Sc.Cno=Course.Cno AND
				  Sc.Sno=Student.Sno));

例三:查询至少选修了学号为“95002”的学生所选修的全部课程的学生学号和姓名

SELECT Sno,Sname
FROM Student
WHERE Sno<>'95002' AND
      NOT EXISTS
     (SELECT *
	  FROM Course
	  WHERE Cno IN(
				SELECT Cno
				FROM Sc
				WHERE Sc.Sno='95002'
			)
	  AND
	  NOT EXISTS
	 (SELECT *
	  FROM Sc
      WHERE Sc.Cno=Course.Cno AND
	        Sc.Sno=Student.Sno ));
	        
--或者

SELECT Sno,Sname
FROM Student
WHERE Sno<>'95002' AND
      NOT EXISTS
	 (SELECT *
	  FROM Sc SCX
	  WHERE  SCX.Sno='95002' AND
	         NOT EXISTS
			(SELECT *
			 FROM Sc SCY
			 WHERE SCY.Cno=SCX.Cno AND
			       SCY.Sno=Student.Sno));

4、集合查询

  • 集合查询概述:SELECT查询后得到的是元组的集合,即n行数据,那么对于这些已经查询得到的集合,我们可以对其进行集合操作,即集合查询。
  • 集合查询前提:各元组集合列数相同,数据类型相应相等。
  • 集合查询操作
    (1)并操作:UNION
    (2)交操作:INTERSECT
    (3)差操作:EXCEPT
    直接将俩个查询间加上集合操作即可。

5、派生表查询

  • 派生表查询:子查询一般出现在WHERE中,但当我们把子查询放到FROM子句中,这时FROM子句下的就是子查询生成的派生表,派生表是临时的是一种很灵活的写法。
  • 举例
    由于学习阶段不常用,我这里只举一个例子:

查询每个学生超过自己选修课平均成绩的课程号,用派生表查询实现

SELECT Sno,Cno
FROM Sc,(SELECT Sno,AVG(Grade) FROM Sc GROUP BY Sno) AS AVG_Sc(Avg_Sno,Avg_Grade)
WHERE Sc.Sno = AVG_Sc.Avg_Sno 
  AND Sc.Grade >= AVG_Sc.Avg_Grade


--下面给派生表一个特写方便理解
(SELECT    Sno,    AVG(Grade)    FROM Sc GROUP BY Sno)
 AS AVG_Sc(Avg_Sno,Avg_Grade)

三、数据更新(数据维护)

1、插入数据

  • 模板
INSERT 
INTO<表名>[(<属性列1>,[<属性列2>...])]
VALUES(<常量1>[,<常量2>...]);

其中:

  1. 若是在INTO后指明了属性列表,则VALUES后要插入的常量就要按照指明的顺序和内容写。一一对应;
  2. 若是没有指明任何属性列,则VALUES后必须要严格对照该表原有属性顺序,且不可以有缺少。
  • 举例

在Student表内插入一段数据:

INSERT
INTO Student (Sno,Sname,Ssex,Sage,Sdent,Smajor)
VALUES ('95001','RETRO','男','20','计算机学院','码农的养成');
INSERT
INTO Student (Sno,Sname,Ssex,Sage,Sdent,Smajor)
VALUES ('95002','RETRO2','男','20','计算机学院','码农的养成');

查询结果:
在这里插入图片描述

2、修改数据

  • 模板
UPDATE Student 
SET <列名> = <表达式>[, <列名> = <表达式>...]
[ WHERE<条件语句> ]
  • 注意事项
  1. 不能直接删除带约束的字段
    应该先删除字段上相关的约束
  2. 不能直接更改字段名
    应该先添加新的字段名,并且将数据重新插入,再删除旧字段。
  3. 修改数据最重要的不是修改本身,而是修改的对象,修改很简单只要把SET为新值就行,但要修改哪些对象则需要考虑如何查询。
  4. 数据的修改是UPDATE 配合 SET 或者 DELETE,注意与表的结构修改 ALTER ADD DROP 作区分。
  • 举例

将学号95002的学生名字改为‘frog’,Sdept改为‘计算机学院隔壁’

UPDATE Student
SET Sname = 'frog',
	Sdept = '计算机学院的隔壁' --注意这里就不用加逗号,
							  --原则上逗号只是用来在相似语句间作分割
WHERE Sno='95002'

3、删除数据

  • 模板
DELETE 
FROM <表名>
[WHERE <条件语句>]
  • 举例
DELETE
FROM Student

四、视图操作

  • 视图概述:视图(VIEW)是一个表(TABLE)或者多个表(或视图)导出来的新表,但本质上是一个虚表,不是基本表,数据库内部不存放视图的数据,只存放其结构的定义,这就使数据库和用户间有了一个“窗口”,既保护了数据库,又方便了操作。

1、定义视图

  • 模板
CREATE VIEW<视图名>[(<列名>[,<列名>])] --列名要么全都指定,要么全都隐含在SELECT中
AS <子查询>
[WITH CHECK OPTION] --加上后对视图更新数据时必须符合SELECT中条件
  • 举例

例一:建立男学生的视图(Male_Student),属性包括学号、姓名、选修课程名和成绩,且要求修改和插入时人需保证该视图只有男学生

CREATE VIEW Male_Student
AS
SELECT Student.Sno,Student.Sname,Course.Cname,Sc.Grade
FROM Student,Sc,Course 
WHERE Student.Sno=Sc.Sno AND
	  Sc.Cno=Course.Cno AND
       Student.Ssex='男'
WITH CHECK OPTION;--加上后对视图更新数据时会自动加上 Student.Ssex='男' 的约束

作为视图,很多时候他的列属性不是单纯的从其他表中选出来的,而是由其他表计算推导出来的,一般会用到聚集函数如AVG、SUM。根据模板内注释,在这种情况下一定要指定视图的所有列名。接下来给出一个例子:

例二:将学生的学号及平均成绩定义为一个视图

CREATE VIEW S_G(Sno,Gavg)
AS
SELECT Sno,AVG(Grade)
FROM Sc
GROUP BY Sno

2、查询视图

与基本表的查询操作类似。

3、更新视图

  • 与基本表的更新操作类似,但要特别注意不是所有视图都能更新。
  • 由于视图是不实际存数据的,也就是说对视图的更新时根据对基本表的更新实现的,所以当我们做一些无法转化为基本表更新的操作时,就会出现不可更新的现象。-
  • 比如上面例子中的平均成绩,我们无法根据视图中的平均成绩转化为每一科的成绩,所以S_G是不可更新的

4、删除视图

  • 模板
DROP VIEW <视图名> [CASCADE];
--加上CASCADE后会连带其导出的所有视图一起删除

五、存储过程和函数

  • 我们知道一般来看SQL是高度非过程化的语言,但SQL存储过程和函数的概念在SQL99标准被支持,在过程化的SQL中每一个程序都是由块构成的,每一个块完成逻辑操作。
  • 过程化SQL块有命名块和匿名块之分,命名块在被编译后保存在数据库中,是持久性存储模块,可以反复快速调用。过程和函数就是命名块,这里主要介绍存储过程

注:存储过程有很多内容,我学习的部分都是网上和书上七零八碎找的,只是为了实现某些功能,所以这里只是冰山一角。但是由于我并不是专业的所以这些只是作简单的学习仅当了解,如要系统学习还有很长很长的路要走。

  • 模板
--创建过程
CREATE PROC[EDURE]  过程名 [<参数1> [,<参数>]...]
AS<过程化SQL>
--更新过程
ALTER PROC[EDURE]  过程名 [<参数1> [,<参数>]...]
AS<过程化SQL>
--调用过程
EXEC 过程名 [参数列表]
--删除过程
DROP PROC[EDURE]  过程名
  • 局部变量赋值
SET @变量名=<表达式>
SELECT @变量名=<表达式>[列表达式组]
 [FROM……] 
  • print输出
 PRINT '<字符串>'+ CONVERT(<数据类型>[(长度)],<表达式>)
  • 举例

忽视例子里的名字中英文区别

例一:设计并调用存储过程,输出学生选修总学分

--作查询
CREATE PROC pro1
AS
SELECT 学生.Sno 学生学号,SUM(课程.Ccredit) 总学分
FROM 学生,课程,选课 
WHERE 学生.Sno=选课.Sno AND 选课.Cno=课程.Cno
GROUP BY 学生.Sno

EXEC pro1

--或者用输入学生号做print
--创建过程
CREATE PROC pro
@THESNO CHAR(20)
AS 
DECLARE @SUMCREDIT SMALLINT

SELECT @SUMCREDIT = SUM(Course.Ccredit)
FROM Student,Sc,Course 
WHERE Student.Sno = Sc.Sno AND Sc.Cno = Course.Cno AND Student.Sno=@THESNO
GROUP BY Student.Sno
PRINT 'CREDIT: '+ convert(varchar(10),@SUMCREDIT)

--调用过程
EXEC pro
@THESNO = '95001'

例二:设计并调用存储过程,输出课程选修总人数

--作查询
CREATE PROC pro2
AS 
SELECT 课程.Cno 课程号,COUNT(*) 选修人数
FROM 学生,课程,选课 
WHERE 学生.Sno=选课.Sno AND 选课.Cno=课程.Cno 
GROUP BY 课程.Cno

EXEC pro2

--或者用输入课程号做print
--创建过程
CREATE PROC pro2
@THECNO CHAR(20)
AS 
DECLARE @SUM INT
SELECT @SUM = COUNT(*)
FROM Student,Sc,Course 
WHERE Student.Sno = Sc.Sno AND Sc.Cno = Course.Cno AND Sc.Cno=@THECNO
GROUP BY Course.Cno
PRINT 'SUM: '+ convert(varchar(10),@SUM)
--调用过程
EXEC pro2
@THECNO = '001'

例三:设计并调用存储过程,输出课程成绩平均分、最高分和最低分

--作查询
CREATE PROC pro3
AS 
SELECT 课程.Cno 课程号,AVG(Grade) 成绩平均分 ,MAX(Grade)最高分,MIN(Grade) 最低分
FROM 学生,课程,选课 
WHERE 学生.Sno=选课.Sno AND 选课.Cno=课程.Cno 
GROUP BY 课程.Cno

EXEC pro3

--或者用输入课程号做print
--创建过程
CREATE PROC pro3
@THECNO CHAR(20)
AS 
DECLARE 
@MAX INT,
@MIN INT,
@AVG INT
SELECT @MAX = MAX(Sc.Grade),@MIN = MIN(Sc.Grade),@AVG = AVG(Sc.Grade)
FROM Student,Sc,Course 
WHERE Student.Sno = Sc.Sno AND Sc.Cno = Course.Cno AND Sc.Cno=@THECNO
GROUP BY Course.Cno
PRINT 'MAX: '+ convert(varchar(10),@MAX)
PRINT 'MIN: '+ convert(varchar(10),@MIN)
PRINT 'AVG: '+ convert(varchar(10),@AVG)

--调用过程
EXEC pro3
@THECNO = '001'

最后:此处跳转到习题总练习

  • 9
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值