SQL语言概述
SQL是结构化查询语言(Structure Query Language),1974年提出,1979年被IBM实现,SQL语言已经成为关系型数据库的标准语言。
包括:
- DDL数据定义语言
- 语句有CREATE ,ALTER ,DROP,操作表,视图,触发器,存储过程
- DML数据操作语言
- 语句有SELECT ,INSERT , UPDATE , DELETE,用于检索和操作数据
- DCL数据控制语言
- 语句有GRANT , DENY , REVOKE,只有sysadmin,数据库创建者,拥有者,安全管理员有权利执行,用来设置或更改数据库用户或角色权限
- 流程控制
- 常用语句有BEGIN...END , IF...ELSE , WHILE , BREAK , GOTO , WAITFOR , RETURN等语
逻辑运算符
- AND
- OR
- NOT
- ALL,所有表达式为true才为true
- ANY,表达式中一个为true则为true
- BETWEEN ,在某个范围内则为true
- EXISTS
- IN ,操作数为表达式列表中的一个则为true。
语句基本格式
SELECT * FROM 表名
WHERE 条件
GROUP BY 字段 HAVING 表达式
ORDER BY 字段 ASC| DESC
说明:GROUP BY子句后可以使用HAVING 短语,用来分组后筛选,HAVING 必须跟随ORDER BY子句使用。
默认情况,查询结构表的标题可以是表的字段名,也可以无标题,还可以使用AS 对字段标题进行修改
USE 销售管理
GO
SELECT 商品名称,型号,销售价-进价 AS 差价,库存 FROM 商品表
GO
![]()
使用查询生成新表,或者临时表
USE 销售管理
GO
SELECT 商品名称,型号,销售价-进价 AS 差价,库存 INTO 商品表附表 FROM 商品表
GO
结果
![]()
临时表的使用
临时表在本次服务器连接过程中有效,一旦服务器断开连接,临时表失效,并被删除。
USE 销售管理
GO
SELECT 商品名称,型号,销售价-进价 AS 差价,库存 INTO #临时商品表 FROM 商品表
GO
![]()
快速生成数据表结构(空白哦)
因为WHERE 1=2不成立,所以就不会检索出符合条件的数据,生成的是一个没有数据的空白表
USE 销售管理
GO
SELECT 商品名称,型号,销售价-进价 AS 差价,库存 INTO #商品表副本 FROM 商品表 WHERE 1=2
GO
SELECT * FROM #商品表副本
![]()
![]()
SQL汇总查询
聚合函数
常用的聚合函数有6个:
- COUNT(*),统计所有记录个数
- COUNT[ DISTINCT] 字段,统计字段中值的个数
- SUM 字段,对指定字段(数值型)求和
- AVG 字段,对指定字段(数值型)求平均值
- MAX 字段,求一个字段最大值
- MIN 字段,求一个字段最小值
分组查询语句
有时候统计每种商品销售总金额,需要对销售表中销售金额进行汇总,然后再进行操作,这就是分组查询。
GROUP BY子句实现,
GROUP BY 字段 HAVING 分组后的筛选条件表达式
注意:BY 字段 按指定字段进行分组,字段值相同的记录放在一组,每一组汇总只有一条数据。
HAVING 的筛选是对经过分组后结果进行筛选,而不是对原始表筛选。
SELECT 子句后的字段列表,必须是聚合函数 ,或者是GROUP BY 子句中的字段。
demo.sql
USE 销售管理
GO
SELECT 品牌,COUNT(品牌) AS 数量 FROM 商品表 GROUP BY 品牌
--HAVING 品牌='A牌'
结果
![]()
注意这里的HAVING子句和WHERE的区别:
HAVING可以有聚集函数,而WHERE子句不可以
HAVING作用于分组后的结果集,WHERE 子句作用于基本表
下面来一个小demo,用来查找某个属性的值出现最多的那个记录
原表
![]()
现在查找哪个品牌数量最多,并找出这个品牌的记录
demo
USE 销售管理
GO
--申明变量用来存储数量最多的品牌
DECLARE @ELE VARCHAR(20)
SELECT @ELE=A.品牌 FROM (SELECT TOP 1 品牌,COUNT(品牌) AS 数量 FROM 商品表 GROUP BY 品牌
ORDER BY 数量 DESC) A
--print @ele
SELECT * FROM 商品表 WHERE 品牌=@ELE
结果集
![]()
汇总合计函数ROLLUP(在sqlserver2008叫做COMPUTE)
使用这个函数,需要最分组函数的最后添加with rollup,然后会在最后多一行。
分组
USE 销售管理
GO
SELECT 品牌,COUNT(品牌) AS 数量 FROM 商品表 GROUP BY 品牌
![]()
使用ROLLUP汇总
USE 销售管理
GO
SELECT 品牌,COUNT(品牌) AS 数量 FROM 商品表 GROUP BY 品牌 WITH ROLLUP
![]()
连接查询
就是多个表单的关联查询
- INNER JOIN,内连接
- LEFT JOIN,左连接,结果包含满足条件的行和左侧表的全部行,使用NULL值代替无法匹配的值
- RIGHT JOIN,右连接
- FULL JOIN,全连接,结果包含满足条件的行和2侧表的全部行
- CROSS JOIN,交叉连接,结果包含2个表的所有行的组合,2个表的笛卡尔操作,用的不多
内连接范例
使用sqlserver语法
USE 销售管理
GO
SELECT A.商品名称,A.品牌,A.销售价,B.类型名称 FROM 商品表 A,商品类型表 B
WHERE A.类型=B.类型编号
![]()
使用ANSI语法
USE 销售管理
GO
SELECT A.商品名称,A.品牌,A.销售价,B.类型名称 FROM 商品表 A
INNER JOIN 商品类型表 B ON A.类型=B.类型编号
![]()
注意:<表名> A的意思是将某个表在这一次查询红命名为A,这样在整个查询中都可以使用A代替该表,简化操作。
子查询
子查询出现的形式:
- 多数情况出现在WHERE 子语句中
- 出现在外部查询的SELECT 子语句中
- 出现在外部查询的FROM 子句中,即把查询结果集看做另外一张表
使用比较运算符的子查询
/*查询一级买家信息*/
SELECT * FROM 买家表
WHERE 级别=
(SELECT 级别编号 FROM 买家级别表 WHERE 级别名称='一级')
使用ALL ANY运算符的子查询
当子查询返回的是单列多值,使用ALL ANY和比较运算符构成特殊查询
- >ANY,表示大于子查询结果的某个值,就是大于查询结果最小值
- =ANY,等于查询结果的某个值,相当于IN
- <ANY,小于查询结果的最大值
- >ALL,大于查询结果最大值
- !=ALL,相当于NOT IN
比如查询那些台式电脑比笔记本电脑的进价还要贵
/*查询那些台式电脑比笔记本电脑的进价还要贵*/
SELECT * FROM 商品表
WHERE 商品名称='台式机' AND 进价>ANY
(SELECT 进价 FROM 商品表 WHERE 商品名称='笔记本')
使用IN运算符的子查询
比如查询进价大于5000的商品销售情况
/*查询进价大于5000的商品销售情况*/
SELECT 商品编号,买家编号 FROM 销售表
WHERE 商品编号 IN
(SELECT 商品编号 FROM 商品表 WHERE 进价>5000)
使用EXISTS运算符的子查询
用来判断子查询是否有结果返回,NOT EXISTS的作用刚好相反
比如查询至少有一次实际销售价比进价还低的商品信息
/*查询至少有一次实际销售价比进价还低的商品信息*/
SELECT * FROM 商品表 A
WHERE EXISTS
(SELECT * FROM 销售表 B
WHERE A.商品编号=B.商品编号 AND B.实际销售价格<A.进价)
由于不需要子查询返回具体值,所以这种子查询的通常返回的列为*的格式
有个查询很难理解,记录如下
查询销售表每种商品(由商品编号区分)销售价格最贵的销售情况
分析:首先将商品种类分组
SELECT 商品编号,MAX(实际销售价格) FROM 销售表
GROUP BY 商品编号
这里还不能输出要求的信息,所以还要使用自连接(自己与自己的一个副本连接)
原表
![]()
经过筛选
/*查询销售表每种商品(由商品编号区分)销售价格最贵的销售情况*/
SELECT * FROM 商品表 A
WHERE 销售价=
(SELECT MAX(销售价) FROM 商品表 B WHERE A.品牌=B.品牌)
ORDER BY 商品编号
![]()
数据库中数据的管理
插入数据INSERT
使用INSERT语句插入数据进数据表,有2种方式:插入单行数据(使用VALUES),插入多行数据(使用SELECT)
插入单行数据
/*插入单行数据*/
INSERT INTO 买家表(买家编号,买家名称,买家电话,级别)
VALUES('M05','薛松','5362313','J02');
当插入数据的数量和顺序和表中字段一一对应,可以省略字段名列表
/*插入单行数据*/
INSERT INTO 买家表
VALUES('M06','宋松','5362220','J02');
插入多行数据
新建一张表,名为“高价销售表类”,结构与销售表相同,将销售表的实际销售价格>3000的记录插入该表。
/*插入多行数据*/
--建立一张空表
SELECT * INTO 高价销售表 FROM 销售表 WHERE 1=2
GO
--插入多行数据
INSERT INTO 高价销售表(商品编号,买家编号,实际销售价格,销售日期,销售数量)
SELECT 商品编号,买家编号,实际销售价格,销售日期,销售数量
FROM 销售表 WHERE 实际销售价格>3000
GO
为了建立一张空白表,查询条件WHERE 1=2永远不成立,这个是一个常用的方法。
将所有一级买家的信息存入新表“高级买家”
/*插入多行数据*/
--创建新表
SELECT * INTO 高级买家 FROM 买家表 WHERE 1=2
GO
--添加数据
INSERT INTO 高级买家
SELECT 买家表.*
FROM 买家表,买家级别表
WHERE 买家表.级别=买家级别表.级别编号 AND 级别名称='一级'
GO
由于查询过程使用了2个表了,所以SELECT 语句要声明,只要买家表的列
修改数据UPDATE
普通修改
因为与A品牌的合作有了新政策,所有A品牌商品进货价下调5%
/*普通修改数据*/
UPDATE 商品表 SET 销售价=销售价*0.95 WHERE 品牌='A牌'
带子查询的修改
为了增加耗材商品的销售份额,公司决定将所有耗材商品销售价格下调5%
/*子查询修改数据*/
UPDATE 商品表 SET 销售价=销售价*0.95
WHERE 商品表.类型=
(SELECT 类型编号 FROM 商品类型表 WHERE 类型名称='耗材')
删除数据DELETE
删除普通数据
删除销售表4所有B牌的商品购买信息
/*删除数据*/
SELECT * INTO 销售表4 FROM 销售表
GO
DELETE FROM 销售表4
WHERE 品牌='B牌'
删除子查询
删除销售表4中所有买家名称为“个人”的买家购买信息
/*删除数据*/
SELECT * INTO 销售表4 FROM 销售表
GO
DELETE FROM 销售表4
WHERE 买家编号=
(SELECT 买家编号 FROM 买家表 WHERE 买家名称='个人')
清空数据表
/*删除数据*/
SELECT * INTO 销售表4 FROM 销售表
GO
TRUNCATE TABLE 销售表4
注意:TRUNCATE TABLE 和不带条件的DELETE最终效果都是清空表中所有数据,但是在执行上TRUNCATE TABLE 更高,速度更快,因为他不记录事务日志,会释放数据,索引占据的空间,删除的数据不可恢复。