5 数据表管理

5.4 使用SQL语句创建表

5.4.1 新建商品类别表

USE E_Market—指向当前所操作的数据库
GO

CREATE TABLE CommoditySort
(
SortId INT IDENTITY(1,1) NOT NULL,—类别号
SortName VARCHAR(50) NOT NULL—类别名称
)
GO

5.4.2 创建商品信息表

USE E_Market
GO
CREATE TABLE CommodityInfo
(
CommodityId INT IDENTITY(1,1) NOT NULL,—商品号
SortId INT NOT NULL,—类别类别,外键
CommodityName VARCHAR(50) NOT NULL,—商品名称
Picture IMAGE,—商品图片
InPrice FLOAT NOT NULL,—商品进价
OutPrice FLOAT NOT NULL,—商品售价
Amount INT NOT NULL—商品库存量
)
GO

5.5 约束的类型

5.5.1 语法

ALTER TABLE 表名
ADD CONSTRAINT 约束名 约束类型 具体的约束说明

5.5.2 命名规则

约束名的取名规则推荐采用:约束类型_约束列

  1. 主键(PRIMARY KEY)约束:如PK_UserId
  2. 维一(UNIQUE KEY)约束:如UQ_UserCardId
  3. 默认(DEFAULT KEY)约束:如DF_UserPasspwd
  4. 检查(CHECK KEY)约束:如CK_Gender
  5. 外键(FOREIGN KEY)约束:如FK_SortId

    5.6 使用SQL语句为表添加约束

    5.6.1 为表UserInfo添加约束

    USE E_Market
    GO
    ALTER TABLE UserInfo
    ADD CONSTRAINT PK_UserId PRIMARY KEY (UserId),
    CONSTRAINT CK_UserPwd CHECK ( LEN ( UserPwd ) >=6 ),
    CONSTRAINT CK_Gender CHECK ( Gender = 0 OR Gender = 1 ),
    CONSTRAINT DF_Gender DEFAULT ( 0 ) FOR Gender,
    CONSTRAINT CK_Email CHECK ( Email LIKE ‘%@%’ )
    GO

    5.6.2 为表OrderInfo添加约束

    USE E_Market
    GO
    ALTER TABLE OrderInfo
    ADD CONSTRAINT PK_OrderId PRIMARY KEY (OrderId),
    CONSTRAINT FK_UserId FOREIGN KEY ( UserId ) REFERENCES UserInfo ( UserId ),
    CONSTRAINT FK_CommodityId FOREIGN KEY (CommodityId) REFERENCES CommodityInfo (CommodityId),
    CONSTRAINT DF_PayWay DEFAULT ( ‘网上银行’ ) FOR PayWay,
    CONSTRAINT CK_Confirm CHECK ( Confirm = 0 OR Confirm = 1 ),
    CONSTRAINT DF_Confirm DEFAULT ( 0 ) FOR Confirm,
    CONSTRAINT CK_SendGoods CHECK ( SendGoods = 0 OR SendGoods = 1),
    CONSTRAINT DF_SendGoods DEFAULT ( 0 ) FOR SendGoods
    GO

    5.6.3 外键约束注意事项:

  6. 类型、长度必须与引用的主键类型、长度完全一致

  7. 引用的表中必须有主键列

    5.6.4 为表CommoditySort添加约束

    USE E_Market
    GO
    ALTER TABLE CommoditySort
    ADD CONSTRAINT PK_SortId PRIMARY KEY (SortId)
    GO

    5.6.5 为表CommodityInfo添加约束

    USE E_Market
    GO
    ALTER TABLE CommodityInfo
    ADD CONSTRAINT FK_SortId FOREIGN KEY (SortId) REFERENCES CommoditySort (SortId)
    GO

    5.7 使用T-SQL向已有数据表添加约束

    5.7.1 语法

    ALTER TABLE 表名 WITH NOCHECK
    ADD CONSTRAINT 约束名 约束类型 具体的约束说明

    5.7.2 说明

    对表中现有的数据不做检查,只对添加约束之后再录入的数据进行检查

    5.7.1 事例

    5.7.1.1 为用户表已有数据的Employee添加约束

    ALTER TABLE Employee WITH NOCHECK
    ADD CONSTRAINT CK_EmployeeId CHECK (LEN (EmployeeId) = 18)
    GO

    5.8 SQL语句删除约束

    5.8.1 语法

    ALTER TABLE 表名
    DROP CONTRANINT 约束名

    5.8.2 事例

    5.8.2.1 删除Employee表中的主键约束

    ALTER TABLE Employee
    DROP CONSTRAINT PK_EmployeeId

    5.9 数据库关系图

  8. 对特定的数据库表进行可视化管理与分析

  9. 一个数据库可以创建多个数据库关系图
  10. 使用系统存储过程改变数据库所以者为当前登录账户EXEC sp_changedbowner sa
  11. 可以清晰的查看表之间的引用关系
  12. 建立引用关系,从主表的主键向子表的引用建拖动
  13. 在设计状态下建主外键关系是从子表向主表建关系
  14. 数据库关系图下是从主表向子表建关系

    image.png

    5.10 删除表

    5.10.1 视图下删除表顺序:

    OrderInfo—>UserInfo—>CommodityInfo—>CommoditySort

    5.10.2 SQL语句删除表语法

    USE E_Market
    GO
    DROP TABLE CommodityInfo
    DROP TABLE CommodityAort
    GO

    5.10.3 如果存在表即删除

    IF EXISTS ( SELECT * FROM sysobjects WHERE name = ‘UserInfo’ )
    DROP TABLE UserInfo
    GO

    6 T-SQL数据语言操作

    6.1 T-SQL中的运算符

    算术运算符:+,-,*,/,%(取mod、取余)
    赋值运算符:=
    逻辑运算符:AND,OR,NOT
    比较运算符:>,<,<=,>=,<>,=
    连接运算符:”+”

    6.1.1 事例

    6.1.1.1 算术运算符

    SELECT 3+4 AS 加的结果;—7
    SELECT 5/2 AS 除的结果;—2
    SELECT 5.0/2 AS 除的结果;—2.500000
    SELECT 5%2 AS 模;—1

    6.1.1.2 赋值运算符

    DECLARE @age INT
    SET @age = 18
    SELECT @age;—18

    6.1.1.3 比较运算符

    DECLARE @x INT, @y INT
    SET @x = 8
    SET @y = 10
    IF @x >= @y
    SELECT ‘@x大于或等于@y的值’
    ELSE
    SELECT ‘@y的值’;—@y的值大

    6.1.1.4 逻辑运算符

    IF (3>5 OR 6<3 AND NOT 6>4)
    SELECT ‘TURE(真)’
    ELSE
    SELECT ‘FALSE(假)’;—FALSE(假)

    6.1.1.5 连接运算符

    DECLARE @color VARCHAR(4)
    SET @color = ‘绿色’
    SELECT ‘我最喜欢的颜色是’ + @color;—我最喜欢的颜色是绿色

    6.1.2 说明

  15. /的左右两边都是整数,结果也是整数;左右两边有一边是非整数,结果为非整数

  16. 5里面有2个2,还多一个1,多的这个数就叫模或是余数
  17. 赋值运算符是将等号右边的值赋给左边的变量或是表达式
  18. AND左右结果都为true(真)时结果为true(真)
  19. OR左右结果有一个为true(真)则结果为ture(真)
  20. NOT是非即取反,真的变成假的,假的变成真的
  21. +左右都是数字型,+就是算术运算符
  22. +左右都是字符型,+就是连接运算符
  23. +左右类型不一致,则需要类型转换

    6.1.3 运算符的优先级

    ()>算法运算符>比较运算符>逻辑运算符>连接运算符>赋值运算符
    NOT>AND>OR

    6.2 使用SSMS操作数据

    6.2.1 解释

    SSMS:SQL Server Managerment Studio

    6.2.2 操作

    插入数据、修改数据、删除数据、查看数据

    6.2.3 说明

  24. 插入数据的顺序先插入主表中的数据,然后再插入子表中的数据

  25. 删除数据先删除子表中的数据,再删除主表中的数据
  26. 标识列不需要手动添加数据

    6.3 使用T-SQL插入数据

    6.3.1 语法

    INSERT [INTO] 表名 [(列名)] VALUES (值列表)
    说明:[]里的字段可以省略

    6.3.2 说明

  27. 每次插入一行数据,不能只插入半行或者几列数据

  28. 每个数据值的数据类型、精度和小数位数必须与相应的列匹配
  29. 向含有标识列的表中插入数据,不能为标识列指定值
  30. 如果在设计表的时候就指定了某列不予许为空,则必须插入数据
  31. 插入的数据项,要求符合检查约束的要求
  32. 具有缺省值的列,可以使用DEFAULT(缺省)关键字来代表插入的数值
  33. 插入数据的表顺序是CommoditySort、CommodityInfo(UserInfo)、OrderInfo

    6.3.3 事例

    6.3.3.1 向表CommoditySort插入数据

    USE E_Market
    GO
    INSERT INTO CommoditySort VALUES
    (‘手机数码’),
    (‘图书音像’),
    (‘家用电器’)

    6.3.3.2 向表UserInfo插入数据

    INSERT UserInfo VALUES
    (‘youyou’,’iloveyou’,’卢晓凤’,’1’,’北京海淀’,’lxf@sohu.com’,’010-82338233’),
    (‘feiyang’,’hongmei’,’段飞扬’,’0’,’武汉江岸’,’dfy@tom.com’,’027-85796644’),
    (‘daxia’,’langyashan’,’赵可以’,’0’,’上海普陀’,’zky@163.com’,’021-58207097’)

    6.3.3.3 向表CommodityInfo插入数据

    INSERT INTO CommodityInfo (SortId, CommodityName, InPrice, OutPrice, Amount) VALUES
    (1,’索尼 Z3’,3300,4299,100),
    (2,’JavaScript指南’,20,50,200),
    (1,’华为荣耀 3C 畅玩’,500,799,80)

    6.3.3.4 向表OrderInfo插入数据

    INSERT INTO OrderInfo (UserId, CommodityId,Amount,PayMoney,PayWay,OrderTime,Confirm,SendGoods) VALUES
    (‘youyou’,1,2,8598,DEFAULT,’2014-03-26’,0,1),
    (‘feiyang’,2,10,500,’邮局汇款’,’2014-02-06’,1,1),
    (‘daxia’,3,3,2397,’银行转账’,’2014-01-08’,1,1)

    6.4 使用T-SQL一次性向表中插入多行数据

    6.4.1 语法

    6.4.1.1 将现有表中数据插入已存在的表中

    INSERT INTO <表名>(列名)
    SELECT <列名>
    FROM <源表名>

    6.4.1.2 将现有表中数据插入新表中

    SELECT (列名)
    INTO <表名>
    FROM <源表名>

    6.4.2 事例

    6.4.2.1 新建一张UserAddress表

    —说明:包含字段UserId、UserName、UserAddress、Phone与UserInfo表中数据类型一致
    USE E_Market
    GO
    IF EXISTS (SELECT * FROM sysobjects WHERE name = ‘UserAddress’)
    DROP TABLE UserAddress
    GO
    CREATE TABLE UserAddress
    (
    UId VARCHAR(16) PRIMARY KEY (UId) NOT NULL,
    UNaem VARCHAR(50) NOT NULL,
    UAddress NVARCHAR(200),
    UPhone VARCHAR(50) NOT NULL
    )
    GO

    6.4.2.2 一次性将表UserInfo中的数据插入到表UserAddress中

    INSERT INTO UserAddress (UId,UNaem,UAddress,UPhone)
    SELECT UserId,UserName,UserAddress,Phone
    FROM UserInfo

    6.4.2.3 一次性将表UserInfo中的数据插入到新表AddressList中

    SELECT UserId, UserName, UserAddress, Phone, IDENTITY (INT,1,1) AS ID
    INTO AddressList
    FROM UserInfo;

    6.5 使用T-SQL更新数据

    6.5.1 语法

    UPDATE 表名 SET 列名 = 更新值
    [WHERE 更新条件]

    6.5.2 说明

  34. 如果要更新的值有多个,那么值与值之间用英文的逗号分隔

  35. WHERE条件不写的话,将更新表中所有的数据
  36. 使用UPDATE更新数据,可能更新一行,可能更新多行,也可能不更新任何数据
  37. 修改数据的三要素

    1. 要修改的表是哪个?
    2. 要修改的列是哪个?
    3. 修改数据的条件是什么?如果条件有多个的话,使用关系运算符(NOT、AND、OR)连接

      6.5.3 事例

      6.5.3.1 更新数据表中所有行的性别

      UPDATE UserInfo SET Gender = 1;

      6.5.3.2 更新数据表中一行数据的一个值

      UPDATE UserInfo SET UserName = ‘张三’ WHERE UserId = ‘youyou’;

      6.5.3.3 更新数据表中一行数据的多个值

      UPDATE UserInfo SET UserName = ‘李四’, Gender = 0 WHERE UserId = ‘daxia’;

      6.5.3.4 更新数据的条件有多个

      UPDATE CommodityInfo SET Amount = 70 WHERE SortId = 1 AND CommodityId = 3;

      6.5.3.5 更新数据不存在,0行受影响

      UPDATE CommodityInfo SET InPrice = 900 WHERE CommodityId = 4;

      6.6 使用T-SQL删除数据

      6.6.1 语法

      DELETE [FROM] 表名 [WHERE <删除条件>]
      TRUNCATE TABLE 表名

      6.6.2 说明

  38. 基本删除,省略HWERE , 将删除表中所有数据

  39. 使用DELETE删除数据后,插入新数据后,标识列持续删除前的增长,不会从标识种子开始
  40. 带条件的删除,是否存在主外键的关系,如果存在,需要先删除子表中的数据,再删除主表的数据

  41. 删除数据的两个要素

    1. 要删除的表是哪个?
    2. 要删除的数据的条件是什么?

      6.6.3 事例

      6.6.3.1 删除表中所有的数据

      DELETE FROM OrderInfo;
      TRUNCATE TABLE OrderInfo;

      6.6.3.2 删除主外键关系的数据

      DELETE OrderInfo WHERE UserId = ‘youyou’;—先删除子表数据
      DELETE UserInfo WHERE UserId = ‘youyou’;—再删除主表数据

      6.6.4 TRUNCATE注意事项

  42. 表结构、列、约束等不被改动,但删除后不能被恢复还原

  43. TRUNCATE TABLE语句不能用于有外键约束的表
  44. 删除数据之后,插入新数据,标识列重新开始从标识种子编号
  45. 用TRUNCATE TABLE删除数据,类似于没有WHERE条件的DELETE语句,删除表中的所有数据

    6.7 数据的导入导出

    6.7.1 定义

  46. 导入数据:从SQL Server的外部数据源中检索数据,然后将数据插入到SQL Server表的过程

  47. 导出数据:将SQL Server中的数据导出指定格式的过程

    6.7.2 说明

  48. 与插入数据的顺序相同,有主外键关系的,先导入主表数据,再导入子表数据

  49. 导数据顺序:先到UserInfo或CommoditySort,再导CommodityInfo,最后导OrderInfo

    6.7.1 数据库导出路径

    点击到导出表所在的数据库—>右键—>任务—>导出数据—>Nicrosoft Excel/平面文件目标

    6.8 批处理

    6.8.1 定义

    批处理是指从应用程序一次性抵发送一组完整SQL语句到SQL Server上执行

    6.8.2 说明

  50. 批处理的所有语句被当做一个整体,被成批地分析,编译和执行。

  51. 所有的批处理指令以GO作为结束的标志
  52. GO的特点

    1. GO语句必须自成一行,只有注释可以在同一行上
    2. 每个批处理单独发送到服务器,一个批处理出错,不会影响里一个批处理的执行
    3. GO语句不是T-SQL命令

      6.8.3 事例

      6.8.3.1 GO语句自成一行

  53. USE E_Market GO—‘GO’ 附近有语法错误。

  54. USE E_Market

    GO SELECT * FROM uase
    GO—GO后面可以重新开始一个批处理,但这样的话会影响可读

    6.8.3.2 每个批处理单独执行

    SELECT 1/0
    GO
    —第一个批处理结束
    SELECT 0/1
    GO
    —第二个批处理结束

    6.9 批处理的应用

    6.9.1 什么情况下使用批处理

    在脚本中一些事情必须发生在另外一件事情之前,或是分开发生的时候,此时需要用到批处理

    6.9.2 事例

    —创建一个TestDB的数据库
    —USE E_Market
    CREATE DATABASE TestDB
    ON PRIMARY
    (
    NAME = ‘TestDB_data’,
    FILENAME = ‘D:\Program Files\Microsoft SQL Server\project\TestDB_data.mdf’,
    SIZE = 3MB
    )
    LOG ON
    (
    NAME = ‘TestDB_log’,
    FILENAME = ‘D:\Program Files\Microsoft SQL Server\project\TestDB_log.ldf’,
    SIZE = 3MB
    )
    GO
    USE TestDB
    GO
    —创建一张TestTable的表
    CREATE TABLE TestTable
    (
    UId INT,
    UName VARCHAR(20)
    )
    GO

    7 数据的查询

    7.1 查询的原理

    7.1.1 语法

    SELECT 列名/* FROM 表名 [WHERE 限制条件] [ORDER BY] 排序

    7.1.2 说明

    在SSMS(SQL Server管理器)或是其他程序的客户端上写一条命令,通过执行按钮,向服务器端(可以是本地的也可以是远程服务器)提交了一个请求,服务端对命令进行编译,结果会以一个虚拟的表形式相应到客户端

    7.1.3 事例

    —查询所有姓李的员工信息
    SELECT * FROM UserInfo WHERE UserName LIKE ‘李%’;

    7.2 简单的查询(1)

    7.2.1 查询全部的行和列

  55. 语法:SELECT * FROM 表名

  56. 事例:

USE E_Market
GO
SELECT * FROM UserInfo;

7.2.2 查询部分的行和列

  1. 语法:SELECT 列名1, 列名2 FROM 表名 WHERE 限制条件
  2. 说明:列使用列名来限制,行使用WHERE条件来限制
  3. 事例:SELECT UserId, PayWay, PayMoney FROM OrderInfo WHERE PayWay <> ‘网上银行’;

    7.2.3 在查询中使用列的别名

  4. 使用 AS 子句来改变结果集中的列名

SELECT UserId AS 用户名, PayWay AS 付款方式, PayMoney AS 付款金额
FROM OrderInfo WHERE PayWay <> ‘网上银行’;

  1. 使用“=”来改变结果集中的列名

SELECT 用户名 = UserId, 付款方式 = PayWay, 付款金额 = PayMoney
FROM OrderInfo WHERE PayWay <> ‘网上银行’;
说明:此处的“=”是赋值运算符,且赋值的顺序是从右往左

  1. 使用“空格”来改变结果集中的列名

SELECT UserId 用户名, PayWay 付款方式, PayMoney 付款金额
FROM OrderInfo WHERE PayWay <> ‘网上银行’;

7.2.4 查询空值 IS NULL

SELECT FROM UserInfo WHERE Email IS NULL;
SELECT
FROM UserInfo WHERE Email IS NULL OR Email = ‘’;
说明:IS NULL和两个单引号’’的区别

  1. IS NULL:从未录入过数据,没有地址
  2. ‘’:录入过地址,而后被删除,是有地址的

    7.3 简单的查询(2)

    7.3.1 在查询中使用常量列

    SELECT UserId 用户名, PayWay 付款方式, PayMoney 付款金额, ‘天猫’ AS 购物网站 FROM OrderInfo;

    7.3.2 查询返回限制的行数

    7.3.2.1 返回限定个数:TOP 个数

  1. 语法:SELECT TOP 个数 列名或* FROM 表名
  2. 事例:SELECT TOP 5 UserName AS 用户名, UserAdress AS 地址 FROM UserInfo WHERE GEnder= 1

    7.3.2.2 返回限定百分比:TOP 百分比 PERCENT

  3. 语法:SELECT TOP 百分比 PERCENT 列名或* FROM 表名

  4. 事例:SELECT TOP 20 PERCENT UserName AS 用户名, UserAddress AS 地址

FROM UserInfo WHERE Gender= 1

  1. 说明:百分比的形式可以取得大概的数据,而非精准的数据,且有余就进1,比如百分比结果1.1,显示2条

    7.3.3 排序查询ORDER BY

  2. 语法:SELECT 列名或* FROM 表名 [WHERE] ORDER BY

  3. 事例:—将订单表中付款金额高到低排序

    SELECT UserId, PayWay, PayMoney FROM OrderInfo ORDER BY PayWay DESC;
    —按购买数量将序,付款金额升序
    SELECT UserId, PayWay, Amount, PayMoney FROM OrderInfo ORDER BY Amount DESC,PayWay;

    7.4 字符串函数

    7.4.1 CHARINDEX

  4. 描述:寻找一个指定的字符串在另一个字符串中的起始位置,如果找到则返回找到的位置,找不到则返回0

  5. 事例:—两个参数,不指定位置,默认从1开始

SELECT CHARINDEX (‘zxw’,’www.51zxw.net’);—7
—三个参数,第一个查找的,第二个是源字符串,第三个是开始查找的位置
SELECT CHARINDEX (‘zxw’,’www.51zxw.net’,10);—0
—查找“葛世阳”的邮箱中“@”符号的位置
SELECT CHARINDEX (‘@’,Email) FROM UserInfo WHERE UserName = ‘葛世阳’;—12

  1. 说明:

    7.4.2 LEN

  2. 描述:返回传递给他的字符串长度

  3. 事例:SELECT LEN (Email) FROM UserInfo WHERE UserName = ‘葛世阳’;—18

    7.4.3 UPPER

  4. 描述:把传递给他的字符串转换为大写

    7.4.4 LTRIM

  5. 描述:清除字符左边的空格

    7.4.5 RTRIM

  6. 描述:清除字符右边的空格

    7.4.6 LEFT

  7. 描述: 从字符串的左边截取指定个数的字符

  8. 事例:SELECT LEFT (Email, CHARINDEX(‘@’,Email)-1)

FROM UserInfo WHERE UserName = ‘葛世阳’;—13472731221

7.4.7 RIGHT

  1. 描述:从字符串的右边截取指定个数的字符

    7.4.8 REPLACE

  2. 描述:替换一个字符串中的字符

  3. 事例:SELECT REPLACE (‘我最喜欢的颜色是白色’,’白色’,’绿色’);—我最喜欢的颜色是绿色

    SELECT REPLACE (‘我最喜欢的颜色是白色’,’白色’,’’);—我最喜欢的颜色是

  4. 说明:此函数有3个参数,如果第三个参数是空的话,相当于将第二个参数删除

    7.4.9 STUFF

  5. 描述:在一个字符串中,删除指定长度的字符,并在该位置插入一个新的字符串

  6. 事例:SELECT STUFF (‘ABCDEF’,2,3,’我要自学网’);—A我要自学网EF
  7. 说明:此函数有4个参数,参数1是源字符串,参数2是开始位置,参数3是删除长度,参数4是插入的新字符串

    7.5 日期函数

    7.5.1 GETDATE

  8. 描述:取得当前的系统日期

  9. 事例:SELECT GETDATE();—2020-11-30 09:57:40.713

    7.5.2 DATEADD

  10. 描述:将指定的数值添加到指定的日期部分后的日期

  11. 说明:此函数有3个参数,参数1是指定的日期部分,参数2是整数值,参数3是有效的日期格式

    参数2的整数允许为负数,指当前日期的往前推的日期
    参数2的整数也允许为小数,但是没有实际意义,会把小数位都舍掉,忽略不计

  12. 事例:SELECT DATEADD (MM,1,GETDATE());—2020-12-30 10:09:54.257

    7.5.3 DATEDIFF

  13. 描述:两个日期之间的指定日期部分的分隔

  14. 说明:此函数有3个参数,参数1是所夸边界的类型,参数2是开始日期,参数3是结束日期
  15. 事例:SELECT DATEDIFF (YY,’2008-8-8’,GETDATE());—12

SELECT DATEDIFF (YY,GETDATE(),’2008-8-8’);—-12

7.5.4 DATENAME

  1. 描述:日期中指定日期部分的字符串形成
  2. 说明:若两个DATEMAME函数之间有“+”,则“+”是连接运算符
  3. 事例:SELECT DATENAME (YY,GETDATE());—2020

SELECT DATENAME (YY,GETDATE())+DATENAME (MM,GETDATE());—202011

7.5.5 DATEPART

  1. 描述:日期中指定日期部分的数值形式
  2. 说明:若两个DATEPATR函数之间有“+”,则“+”是算术运算符
  3. 事例:SELECT DATEPART (YY,GETDATE());—2020

SELECT DATEPART (YY,GETDATE())+DATEPART (MM,GETDATE());—2031

7.6 数学函数和系统函数

7.6.1 数学函数

7.6.1.1 RAND

  1. 描述:返回从0到1之间的随即float值
  2. 说明:此函数只有1个参数,也称随机种子,且可以省略,如果指定随机种子,则返回随机数相同
  3. 事例:SELECT RAND(100);—0.715436657367485

    7.6.1.2 ABS

  4. 描述:取数值表达式的绝对值

  5. 说明:正数的绝对值是本身,负数的绝对值是相反数,0的绝对值是0
  6. 事例:SELECT ABS (123);—123

SELECT ABS (-123);—123
SELECT ABS (0);—0

7.6.1.3 CEILING

  1. 描述:英文意思是天花板,取大于或等于指定数值、表达式的最小整数
  2. 说明:若是正数,则进位取大值,若是负数,则舍位取大值
  3. 事例:SELECT CEILING (9.00001);—10

SELECT CEILING (-9.00001);—-9

7.6.1.4 FLOOR

  1. 描述:英文意思是地板,取小于或等于指定表达式的最大整数
  2. 说明:若是正数,则舍位取小值,若是负数,则进位取小值
  3. 事例:SELECT FLOOR (9.99999);—9

SELECT FLOOR (-9.00001);—-10

7.6.1.5 POWER

  1. 描述:取数值表达式的幂值
  2. 事例:SELECT POWER (4,3);—64

    7.6.1.6 ROUND

  3. 描述:将数值表达式四舍五入为指定精度

  4. 说明:此函数包含2个参数,参数1是有效的数值类型,参数2是保留小数的位数的整数表达式
  5. 事例:SELECT ROUND (123.454,2);—123.450

SELECT ROUND (-123.456,2);—-123.460

7.6.1.7 SIGN

  1. 描述:对于整数返回+1,对于负数返回-1,对于0则返回0
  2. 事例:SELECT SIGN(123.45);—1.00

SELECT SIGN(-123.45);—-1.00
SELECT SIGN(0);—0

7.6.1.8 SQRT

  1. 描述:取浮点表达式的平方根
  2. 事例:SELECT SQRT(144);—12

    7.6.2 系统函数

    7.6.2.1 CONVERT

  3. 描述:用来转变数据类型

  4. 事例:将字符型转换为数字型

SELECT CONVERT (INT,’12’) + CONVERT (INT,’10’);—22,此处“+”是算术运算符
将数字型转换为字符型
SELECT CONVERT (VARCHAR(2),12) + CONVERT (VARCHAR(2),10);—1210,此处“+”是连接运算符
将日期型转为字符型
SELECT CONVERT (VARCHAR(10),GETDATE(),102);—2020.11.30

不带世纪数位 (yy) () 带世纪数位 (yyyy) 标准 输入/输出 ()
- 0100 ( ) 默认 mon dd yyyy hh:miAM(或 PM)
1 101 美国 mm/dd/yyyy
2 102 ANSI yy.mm.dd
3 103 英国/法国 dd/mm/yyyy
4 104 德国 dd.mm.yy
5 105 意大利 dd-mm-yy
6 106 - dd mon yy
7 107 - mon dd, yy
8 108 - hh:mi:ss
- 9109 ( ) 默认设置 + 毫秒 mon dd yyyy hh:mi:ss:mmmAM(或 PM)
10 110 美国 mm-dd-yy
11 111 日本 yy/mm/dd
12 112 ISO yymmdd
yyyymmdd
- 13113 ( ) 欧洲默认设置 + 毫秒 dd mon yyyy hh:mi:ss:mmm(24h)
14 114 - hh:mi:ss:mmm(24h)
- 20120 () ODBC 规范 yyyy-mm-dd hh:mi:ss(24h)
- 21121 () ODBC 规范(带毫秒) yyyy-mm-dd hh:mi:ss.mmm(24h)
- 126 () ISO8601 yyyy-mm-ddThh:mi:ss.mmm(无空格)
- 127() 带时区 Z 的 ISO8601 yyyy-mm-ddThh:mi:ss.mmmZ
(无空格)
- 130 ( ) 回历 () dd mon yyyy hh:mi:ss:mmmAM
- 131 () 回历 () dd/mm/yy hh:

7.6.2.2 CURRENT_USER

  1. 描述:返回当前用户的名字
  2. 事例:SELECT CURRENT_USER;—dbo

    7.6.2.3 DATALENGTH

  3. 描述:返回用于指定表达式的字节数

    7.6.2.4 HOST_NAME

  4. 描述:返回当前用户所登录的计算机名字

    7.6.2.5 SYSTEM_USER

  5. 描述:返回当前所登录的用户名称

  6. 事例:SELECT SYSTEM_USER;—sa

    7.6.2.6 USER_NAME

  7. 描述:从给定的用户ID返回用户名

    7.7 模糊查询

    7.7.1 通配符定义

    通配符指一类字符,代替一个或多个真正的字符。通常与LIKE关键字一起使用。

    7.7.2 通配符类型

    7.7.2.1 _

  8. 描述:一个字符

    7.7.2.2 %

  9. 描述:包含零个或是多个字符的任意字符串

    7.7.2.3 []

  10. 描述:指定范围【0-9】或集合【0123】中的任意字符

    7.7.2.4 [^]

  11. 描述:不在指定范围【a-z】或集合【234】中的任意字符

    7.7.3 模糊查询类型

    7.7.3.1 LIKE

  12. 语法:SELECT 列名或* FROM 表名 WHERE 列名 LIKE ‘%字符%’

  13. 事例:—查询地址中包含四川的用户信息

SELECT * FROM UserInfo WHERE UserAddress LIKE ‘%四川%’;
—查询姓于且只有一个字的员工姓名
SELECT UserName FROM UserInfo WHERE UserName LIKE ‘于_’;—于波
—查询姓李的用户的姓名、地址和电话
SELECT UserName, UserAddress, Phone FROM UserInfo WHERE UserName LIKE ‘李%’;

  1. 特点:

    1. LIKE只能与字符型一起使用
    2. 对于查询结果中的个数不确定

      7.7.3.2 BETWEEN···AND···

  2. 语法:SELECT 列名或* FROM 表名 WHERE 列名 BETWEEN 小值 AND 大值

  3. 事例:—查询订单表中购买数量在2到10之间的订单信息

SELECT FROM OrderInfo WHERE Amount BETWEEN 2 AND 10;
等价于
SELECT
FROM OrderInfo WHERE Amount >= 2 AND Amount <= 10;
—查询下单日期不在‘2014-3-1’到‘2014-3-30’之间的订单信息
SELECT * FROM OrderInfo WHERE OrderTime NOT BETWEEN ‘2014-3-1’ AND ‘2014-3-30’;

  1. 特点:

    1. 查询包含起始值
    2. 起始值小于终值
    3. BETWEEN实际是大于等于、AND是小于等于的意思
    4. 可以与数字型、日期型一起使用

      7.7.3.3 IN

  2. 语法:SELECT 列名或* FROM 表名 WHERE 列名 IN (值1,值2,值3······)

  3. 事例:查询使用‘网上银行’和‘邮局汇款’方式下单的信息

SELECT FROM OrderInfo WHERE PayWay IN (‘网上银行’,’邮局汇款’);
相当于
SELECT
FROM OrderInfo WHERE PayWay = ‘网上银行’ OR PayWay = ‘邮局汇款’;

  1. 特点:

    1. 可以与字符型、数字型、日期型一起使用
    2. 通常用于子查询
    3. 相当于使用OR进行连接的查询

      7.8 聚合函数

      7.8.1 sum()

  2. 描述:返回表达式中所有数值的总和

  3. 事例:—查询商品编号是2个销售总量

SELECT SUM(Amount) AS 总销量 FROM OrderInfo WHERE CommodityId = 2;
—查询商品编号是2的销售总量和付款方式
SELECT SUM(Amount) AS 总销量, PayWay
FROM OrderInfo
WHERE CommodityId = 2
GROUP BY PayWay;

  1. 特点:

    1. 空值将被忽略
    2. 只能与数值型一起使用

      7.8.2 AVG()

  2. 描述:返回表达式中所有数值的平均值,空值将被忽略。只能用于数字类型的列

  3. 事例:—【1】查询图书音像的平均进货价

    —(1)根据商品类型“图书音像”查询类型编号
    SELECT SortId FROM CommoditySort WHERE SortName = ‘图书音像’;—2
    —(2)根据商品类型“2”查找平均进价
    SELECT AVG(InPrice) AS 平均进价 FROM CommodityInfo WHERE SortId = 2;—20

  4. 特点:

    1. 空值将被忽略
    2. 只能与数值型一起使用

      7.8.3 MAX()

  5. 描述:返回表达式中的最大值

  6. 事例:—【1】查询手机数码的最高进货价

    —(1)根据商品类型“手机数码”查询类型编号
    SELECT SortId FROM CommoditySort WHERE SortName = ‘手机数码’;—1
    —(2)根据商品类型“1”查询最高进货价
    SELECT MAX(InPrice) AS 最高进价 FROM CommodityInfo WHERE SortId = 1;—3300

  7. 特点:

    1. 空值将被忽略
    2. 可以与数字型、字符型及日期时间类型一起使用

      7.8.4 MIN()

  8. 描述:返回表达式中的最小值

  9. 事例:—【1】查询手机数码的最低进货价

    —(1)根据商品类型“手机数码”查询类型编号
    SELECT SortId FROM CommoditySort WHERE SortName = ‘手机数码’;—1
    —(2)根据商品类型“1”查询最低进货价
    SELECT MIN(InPrice) AS 最低进价 FROM CommodityInfo WHERE SortId = 1;—500

  10. 特点:

    1. 空值将被忽略
    2. 可以与数字型、字符型及日期时间类型一起使用

      7.8.5 COUNT()

  11. 描述:返回提供的组或记录几种的计数

  12. 事例:—统计用户表中用户数量

SELECT COUNT(UserId) AS 用户数 FROM UserInfo;—13
SELECT COUNT(*) AS 用户数 FROM UserInfo;—13
SELECT COUNT(1) AS 用户数 FROM UserInfo;—13
SELECT COUNT(Email) AS 用户数 FROM UserInfo;—10

  1. 特点:

    1. 如果写列名,空值将被忽略,否则,空值将被统计
    2. COUNT(*)或是常量列如COUNT(1),对所有的行进行计数,包括空值的行

      7.8.6 聚合函数特点

  2. 聚合函数返回结果为单行单列

  3. 查询结果中如果有一个使用了聚合函数,那么就不允许存在非聚合函数项,如果有必须使用GROUP BY子句

    7.9 分组查询

7.9.1 语法

SELECT 聚合函数,分组的列 FROM 表名 [WHERE 条件] GROUP BY 分组的列

7.9.2 事例

  1. 查询用户表中总人数

SELECT COUNT(*) AS 总人数 FROM UserInfo;—10

  1. 查询用户表中男用户的人数

SELECT COUNT(*) AS 男用户数 FROM UserInfo WHERE Gender = 0;—10

  1. 查询用户表中女用户的人数

SELECT COUNT(*) AS 女用户数 FROM UserInfo WHERE Gender = 1;—3

  1. 查询用户表中男女用户总人数

SELECT Gender AS 性别, COUNT(*) 总人数 FROM UserInfo GROUP BY Gender;—0,10;1,3

  1. 查询每项商品的销售总量并按降序排列

SELECT CommodityId AS 商品类型, SUM(Amount) AS 销售总量
FROM OrderInfo
GROUP BY CommodityId
ORDER BY SUM(Amount) DESC;

  1. 查询销售总量超过10的商品信息,并按降序排序

SELECT CommodityId AS 商品类型, SUM(Amount) AS 销售总量
FROM OrderInfo
GROUP BY CommodityId
HAVING SUM(Amount) >= 10
ORDER BY SUM(Amount) DESC;

  1. 查询在2013-01-01到2014-12-31期间销售总量超过3的商品信息,并按降序排序

SELECT CommodityId AS 商品类型, SUM(Amount) AS 销售总量
FROM OrderInfo
WHERE OrderTime BETWEEN ‘2013-01-01’ AND ‘2014-12-31’
GROUP BY CommodityId
HAVING SUM(Amount) >= 3
ORDER BY SUM(Amount) DESC;

7.9.3 说明

  1. 对查询的列有限制,除了聚合函数外,就必须是分组的项
  2. 小技巧:“每”、“各”后边的名称,往往就是分组的项
  3. 分组前的筛选条件用WHERE,分组后的筛选用HAVING子句

    7.10 内连接查询

    7.10.1 定义

    多表连接查询实际上是通过各个表之间共同列的关联性来查询数据的,它是关系数据库查询最主要的特征

    7.10.2 分类

  4. 内连接:根据表中共同的列来进行匹配

  5. 外连接:

    7.10.3 特点

  6. 两个表存在主外键关系

  7. 参与查询的两个表的地位相同,无主次之分

    7.10.4 实现

  8. 使用WHERE子句指定连接条件(先将2个表的数据相乘即笛卡尔积,然后通过WHERE条件选出重叠部分)

  9. 在FROM子句中使用INNER JOIN···ON连接

    7.10.5 事例

  10. 查询订单编号、用户姓名、购买数量、购买商品名称

SELECT OrderInfo.OrderId, UserInfo.UserName, OrderInfo.Amount, CommodityInfo.CommodityName
FROM OrderInfo, UserInfo, CommodityInfo
WHERE OrderInfo.UserId = UserInfo.UserId
AND OrderInfo.CommodityId = CommodityInfo.CommodityId;
等价于
SELECT O.OrderId, U.UserName, O.Amount, C.CommodityName
FROM OrderInfo AS O, UserInfo AS U, CommodityInfo AS C
WHERE O.UserId = U.UserId
AND O.CommodityId = C.CommodityId;
等价于
SELECT OrderId, UserName, O.Amount, CommodityName
FROM OrderInfo AS O
INNER JOIN UserInfo AS U ON O.UserId = U.UserId
INNER JOIN CommodityInfo AS C ON O.CommodityId = C.CommodityId;

7.11 外连接查询

7.11.1 描述

至少返回一个表中的所有记录,根据匹配条件有选择性地返回另一张表的记录

7.11.2 特点

  1. 参与外连接的表有主从之分
  2. 以主表的每行数所匹配从表的数据列将符合条件的数据直接返回到结果集中
  3. 对那些不符合连接条件的列,将被填上NULL值后再返回到结果集中
  4. LEFT JOIN左外连接,以LEFT左边的表为主表,RIGHT JOIN右外连接,以RIGHT右边的表为主表

    7.11.3 分类

    7.11.3.1 左外连接

  5. 描述:包含LEFT JOIN···ON子句中指定的左表的所有行。若左表的某行在右表中有匹配行,则在相关联的结果集中右表的所有选择列均为空值。

  6. 事例:—查询所有商品的当前库存情况,所有商品都要显示出来,以商品信息表为主

SELECT T1.SortId, T1.SortName, T0.CommodityId, T0.CommodityName
,T0.Amount - ISNULL(T2.Amount,0) AS 当前库存
FROM CommodityInfo T0
LEFT JOIN CommoditySort T1 ON T0.SortId = T1.SortId
LEFT JOIN OrderInfo T2 ON T0.CommodityId = T2.CommodityId
ORDER BY T1.SortId ASC, T0.CommodityId ASC;
—查询所有商品类型的销量情况,所有商品类型都要显示,以商品类型表为主
SELECT T0.SortId, T0.SortName, T1.CommodityId, T1.CommodityName, T2.Amount
FROM CommoditySort T0
LEFT JOIN CommodityInfo T1 ON T1.SortId = T0.SortId
LEFT JOIN OrderInfo T2 ON T1.CommodityId = T2.CommodityId
ORDER BY T0.SortId ASC, T1.CommodityId ASC;

7.11.3.2 右外连接

  1. 描述:包含RIGHT JOIN···ON子句中右表所有的匹配行。若右表中有的项在左表中未找到,则以NULL值填充
  2. 事例:用户下单的商品名称和订单号,显示所有商品名称,未下单的用NULL列示

    SELECT T1.CommodityName AS 商品名, T0.OrderId AS 订单号
    FROM OrderInfo T0
    RIGHT JOIN CommodityInfo T1 ON T0.CommodityId = T1.CommodityId
    ORDER BY T0.OrderId;

    7.11.4 转换

    /查询商品类别名称、商品名称以及库存量
    左外连接
    /
    SELECT T0.SortName AS 商品类别名, T1.CommodityName AS 商品名, T1.Amount AS 库存量
    FROM CommoditySort T0
    LEFT JOIN CommodityInfo T1 ON T0.SortId = T1.SortId
    ORDER BY T0.SortId, T1.Amount DESC;
    —等价于右外连接
    SELECT T1.SortName AS 商品类别名, T0.CommodityName AS 商品名, T0.Amount AS 库存量
    FROM CommodityInfo T0
    RIGHT JOIN CommoditySort T1 ON T0.SortId = T1.SortId
    ORDER BY T1.SortId, T0.Amount DESC;

    7.12 使用UNION合并查询(1)

    7.12.1 语法

    SELECT ··· FROM 表名1
    UNION
    SELECT ··· FROM 表名2

    7.12.2 特点

  3. 合并的表中列的个数、数据类型必须相同或者是兼容

  4. 列的名称由第一个SELECT语句中的列名决定
  5. 行数由各表中的行数之和决定,若有重复行默认舍掉
  6. 如果允许有重复行,则需要用UNION ALL
  7. 执行顺序为从上向下(可通过列的顺序或空格改变结果集的排序顺序)
  8. 可以与保存到新表INTO一起使用,但是INTO必须放在第一个SELECT语句中
  9. 可以对合并的结果进行排序,那么ORDER BY必须放到最后一个SELECT中,所使用的列名也必须是第一个SELECT里面的

    7.12.3 事例

  10. 合并前后表的列数和数据类型必须相同或兼容

SELECT UserId AS 用户号, UserName AS 用户名, UserAddress AS 用户地址
FROM UserInfo
UNION
SELECT PayWay AS 付款方式, UserId AS 下单用户号, CONVERT (VARCHAR(10), OrderTime) AS 下单时间
FROM OrderInfo;

  1. 合并表的顺序通过列的顺序改变

SELECT UserId AS 用户号, UserName AS 用户名, UserAddress AS 用户地址
FROM UserInfo
UNION
SELECT UserId AS 下单用户号 ,PayWay AS 付款方式, CONVERT (VARCHAR(10), OrderTime) AS 下单时间
FROM OrderInfo;

  1. 将合并的表保存到一个新表NewTable中

SELECT UserId AS 用户号, UserName AS 用户名, UserAddress AS 用户地址
INTO NewTable
FROM UserInfo
UNION
SELECT UserId AS 下单用户号 ,PayWay AS 付款方式, CONVERT (VARCHAR(10), OrderTime) AS 下单时间
FROM OrderInfo;

  1. 对合并后的表进行排序

SELECT UserId AS 用户号, UserName AS 用户名, UserAddress AS 用户地址
FROM UserInfo
UNION
SELECT UserId AS 下单用户号 ,PayWay AS 付款方式, CONVERT (VARCHAR(10), OrderTime) AS 下单时间
FROM OrderInfo
ORDER BY UserAddress DESC;

7.13 使用UNION合并查询(2)

7.13.1 合并查询和连接查询区别

  1. 合并查询:结果集中的列由第一个表中的列决定,行的最大数量是两个表行的“和”
  2. 连接查询:结果集中的列分别来自不同的表,行的最大数量是两个表行的“乘积”
  3. 结构图: A 合并的结构

B 连接的结构 AB

  1. 事例:
    1. 合并查询 UNION

SELECT UserId, UserName, UserAddress
FROM UserInfo—13行数据
UNION
SELECT UserId, PayWay, CONVERT (VARCHAR(10), OrderTime)
FROM OrderInfo;—12行数据,合并后表25行数据
b. 连接查询 WHERE
SELECT UserInfo.UserId, UserName, UserAddress, PayWay, OrderTime
FROM UserInfo, OrderInfo—不加WHERE条件,产生笛卡尔积,即156行数据
WHERE UserInfo.UserId = OrderInfo.UserId;—12行数据
c. 连接查询 INNER JOIN···ON
SELECT U.UserId, UserName, UserAddress, PayWay, OrderTime
FROM UserInfo U
INNER JOIN OrderInfo O ON U.UserId = O.UserId;—12行数据

7.14 简单子查询(1)

7.14.1 描述

在一个查询语句中包含了另外一个查询语句,查询语句叫做父查询,被包含的查询语句叫子查询

7.14.2 语法

SELECT ···FROM 表1 WHERE 列1 =/> (子查询)

7.14.3 特点

  1. 子查询必须放在一对小括号内
  2. “=”比较运算符,还可以与其他的比较运算符一起使用,要求子查询的列只能有一个
  3. 子查询通常作为WHERE的条件
  4. 子查询中不能出现ORDER BY子句,ORDER BY子句只能出现在父查询中

    7.14.4 事例

  5. 查询手机数码的商品信息

—根据已知项去查未知项,已知项是商品类别名称,未知项是商品信息
—a. 根据商品类别名称查商品类别编号
SELECT SortId FROM CommoditySort WHERE SortName = ‘手机数码’;
—b. 根据商品类别编号查询商品信息
SELECT * FROM CommodityInfo WHERE SortId =
(
SELECT SortId FROM CommoditySort WHERE SortName = ‘手机数码’
)
ORDER BY Amount ASC;

7.15 简单子查询(2)

7.15.1 特点

通常情况下,多表连接查询都可以用子查询替换,但不是所有的子查询都能被表连接查询替换

7.15.2 应用

  1. 子查询:适合于作为查询的WHERE条件,而子查询只能查询主表的字段
  2. 多表连接查询:使用于从多表中查看数据,连接查询可以查看连接表中的任意字段

    7.15.3 事例

    —查询购买小米10青春版手机的客户的姓名和住址

  3. 多表连接查询

SELECT U.UserName, U.UserAddress
FROM OrderInfo O
INNER JOIN UserInfo U ON O.UserId = U.UserId
INNER JOIN CommodityInfo C ON O.CommodityId = C.CommodityId
WHERE C.CommodityName = ‘小米10青春版’;

  1. 子查询

—a. 根据商品名称查询商品编号
SELECT CommodityId FROM CommodityInfo WHERE CommodityName = ‘小米10青春版’;
—b. 根据a中得到的商品编号查询用户编号
SELECT UserId FROM OrderInfo WHERE CommodityId =
(
SELECT CommodityId FROM CommodityInfo WHERE CommodityName = ‘小米10青春版’
);
—c. 根据b中得到的用户编号查询用户姓名和住址
SELECT UserName, UserAddress FROM UserInfo WHERE UserId =
(
SELECT UserId FROM OrderInfo WHERE CommodityId =
(
SELECT CommodityId FROM CommodityInfo WHERE CommodityName = ‘小米10青春版’
)
);

7.16 IN和NOT IN子查询

7.16.1 特点

  1. IN后面的子查询可以返回多条记录
  2. 常用IN替换比较运算符等于(=)的比较子查询

    7.16.2 语法

    SELECT ···FROM ···WHERE 查询表达式 IN(子查询)

    7.16.3 应用

  3. IN:使用IN关键字可以使父查询匹配子查询返回的多个单列值

  4. NOT IN:将父查询条件中的表达式与子查询返回的结果进行比较,把不匹配的信息显示出来

    7.16.4 事例

    —1. 查询购买叶倩文CD-粤语的客户的所有信息
    —a. 根据商品名称查询商品编号
    SELECT CommodityId FROM CommodityInfo WHERE CommodityName = ‘叶倩文CD-粤语’;
    —b. 根据a中得到的商品编号查询用户编号
    SELECT UserId FROM OrderInfo WHERE CommodityId =
    (
    SELECT CommodityId FROM CommodityInfo WHERE CommodityName = ‘叶倩文CD-粤语’
    );
    —c. 根据b中得到的用户编号查询用户的所有信息
    SELECT FROM UserInfo WHERE UserId IN
    (
    SELECT UserId FROM OrderInfo WHERE CommodityId =
    (
    SELECT CommodityId FROM CommodityInfo WHERE CommodityName = ‘叶倩文CD-粤语’
    )
    );
    —2. 从未购买过商品的客户的所有信息
    —a. 查询购买过商品的用户编号
    —使用DISTINCT将多次下单的用户编号去重
    SELECT DISTINCT UserId FROM OrderInfo;
    —b. 从用户表中将购买过商品的用户去除,就是未购买过商品的客户
    SELECT
    FROM UserInfo WHERE UserId NOT IN
    (
    SELECT UserId FROM OrderInfo
    );

    7.17 EXISTS子查询

7.17.1 特点

  1. 只注重子查询是否有返回行,如查有返回行返回结果为真,否则为假
  2. 不使用子查询的结果,仅用于测试子查询是否有返回结果
  3. 通常会用NOT EXISTS对子查询的结果进行取反,即查不到结果为真,否则为假

    7.17.2 语法

    IF EXISTS (子查询)
    [BEGIN]
    语句块
    [END]

    7.17.3 事例

  4. 检查数据库E_Market是否存在,存在就删除,不存在就新建数据库E_Market
    IF EXISTS(SELECT FROM sysdatabases WHERE name = ‘E_Market’)
    DROP DATABASE E_Market
    GO
    CREATE DATABASE E_Market
    (
    )
    GO
    2. 一次性购买“手机数码”产品的数量超过3个,消费金额打8折
    —a. 根据类别名称查询类别编号
    SELECT SortId FROM CommoditySort WHERE SortName = ‘手机数码’
    —b. 根据a得到的类别编号查询商品编号
    SELECT CommodityId FROM CommodityInfo WHERE SortId =
    (
    SELECT SortId FROM CommoditySort WHERE SortName = ‘手机数码’
    )
    —c. 根据b中得到的商品编号查询订单表中数量超过2个的订单信息
    SELECT
    FROM OrderInfo
    WHERE Amount >2 AND CommodityId IN
    (
    SELECT CommodityId FROM CommodityInfo WHERE SortId =
    (
    SELECT SortId FROM CommoditySort WHERE SortName = ‘手机数码’
    )
    )
    —d. 对c中查询的订单编号的付款金额打8折
    IF EXISTS ( SELECT FROM OrderInfo
    WHERE Amount >2 AND CommodityId IN
    (
    SELECT CommodityId FROM CommodityInfo WHERE SortId =
    (
    SELECT SortId FROM CommoditySort WHERE SortName = ‘手机数码’
    )
    )
    )
    BEGIN
    —对付款金额打8这
    UPDATE OrderInfo SET PayMoney = PayMoney
    0.8
    WHERE OrderId IN
    (
    SELECT OrderId FROM OrderInfo
    WHERE Amount >2 AND CommodityId IN
    (
    SELECT CommodityId FROM CommodityInfo WHERE SortId =
    (
    SELECT SortId FROM CommoditySort WHERE SortName = ‘手机数码’
    )
    )
    )
    END

    7.18 ALL、ANY、SOME子查询

7.18.1 描述

  1. ALL:所有
  2. ANY:部分
  3. SOME:与ANY等同,使用ANY的地方都可以使用SOME替换

    7.18.2 事例

    USE E_Market
    GO
    1. 创建第一张表table1
    IF EXISTS ( SELECT FROM sysobjects WHERE name = ‘table1’)
    DROP TABLE talbe1
    CREATE TALBE table1
    (
    n INT
    )
    2. 向第一张表中插入测试数据
    INSERT INTO table1 VALUES (2)
    INSERT INTO table1 VALUES (3)
    -3. 创建第二张表table2
    IF EXISTS ( SELECT
    FROM sysobjects WHERE name = ‘table2’)
    DROP TABLE table2
    CREATE TABLE table2
    (
    n INT
    )
    4. 向第二张表中插入测试数据
    INSERT INTO table2 VALUES (1)
    INSERT INTO table2 VALUES (2)
    INSERT INTO table2 VALUES (3)
    INSERT INTO table2 VALUES (4)
    -5. 查看两个表中的数据
    SELECT FROM table1;—2,3
    SELECT
    FROM table2;—1,2,3,4

    7.18.2.1 >ALL

  4. 描述:父查询中列的值必须大于子查询返回的值列表的每一个值

  5. 事例:SELECT * FROM table2 WHERE n > ALL ( SELECT n FROM table1);—4

    7.18.2.2 >ANY等价于>SOME

  6. 描述:法查询的返回值必须至少大于子查询中的一个值

  7. 事例:

SELECT FROM table2 WHERE n > ANY ( SELECT n FROM table1);—3,4
等价于
SELECT
FROM table2 WHERE n > SOME ( SELECT n FROM table1);—3,4

7.18.2.3 =ANY等价于IN

  1. 描述:与IN等效,父查询中列的值必须在子查询返回值列表中存在
  2. 事例:

SELECT FROM table2 WHERE n = ANY ( SELECT n FROM table1);—2,3
等价于
SELECT
FROM table2 WHERE n IN ( SELECT n FROM table1);—2,3

7.18.2.4 <>ANY相当于OR

  1. 描述:父查询的结果中的列的值与子查询返回值列表中只要有一个不相同就返回
  2. 事例:SELECT * FROM table2 WHERE n <> ANY ( SELECT n FROM table1);—1,2,3,4

    7.18.2.5 NOT IN相当于AND

  3. 描述:父查询的结果中的列的值必须不能存在于子查询中

  4. 事例:SELECT * FROM table2 WHERE n NOT IN ( SELECT n FROM table1);—1,4

    7.19 子查询注意事项

7.19.1 说明

任何允许使用表达式的地方都可以使用子查询

7.19.2 语法

  1. 嵌套在SELECT语句中的子查询

SELECT (子查询) FROM 表名

  1. 嵌套在FROM语句中的子查询

SELECT ··· FROM (子查询) AS 表的别名

7.19.3 事例

  1. 子查询做为SELECT中的列来使用

—a. 商品类别编号为1的商品类别名称
SELECT SortName FROM CommoditySort WHERE SortId = 1
—b. 查询商品类别编号为1的商品名称和类别名称
SELECT CommodityName AS 商品名称,
(SELECT SortName FROM CommoditySort WHERE SortId = 1) AS 类别名称
FROM CommodityInfo
WHERE SortId = 1

  1. 子查询做为FRON中的表来使用

—a. 查询商品信息表中商品类别的库存量大于500的品类编号和库存量
SELECT DISTINCT SortId AS 品类编号, SUM (Amount) AS 库存量
FROM CommodityInfo
GROUP BY SortId
HAVING SUM (Amount) > 500
—b. 将a中查询的品类编号和库存量作为表查询品类名称和库存量
SELECT T0.SortName AS 品牌名称, T1.库存量 AS 库存量
FROM CommoditySort T0
INNER JOIN
(
SELECT DISTINCT SortId AS 品类编号, SUM (Amount) AS 库存量
FROM CommodityInfo
GROUP BY SortId
HAVING SUM (Amount) > 500
) T1 ON T0.SortId = T1.品类编号

  1. 将E_Market数据库中的四张表上的信息全部显示到一张表上

SELECT T0.OrderId AS 订单编号, T0.UserId AS 客户编号, T1.UserName AS 客户名称
, T0.PayWay AS 付款方式, T0.OrderTime AS 下单时间, T0.CommodityId AS 商品编号
, T2.CommodityName AS 商品名称, T2.SortId AS 品类编号, T3.SortName AS 品类名称
, T0.Amount AS 销售数量, T2.Amount-T0.Amount AS 剩余库存
, T2.InPrice AS 进货价格, T2.OutPrice AS 出货价格
, CASE WHEN T0.Confirm = 0 THEN ‘已审批’ ELSE ‘未审批’ END AS 是否审批
, CASE WHEN T0.SendGoods = 1 THEN ‘已发货’ ELSE ‘未发货’ END AS 是否发货
FROM OrderInfo T0
INNER JOIN UserInfo T1 ON T0.UserID = T1.UserId
INNER JOIN CommodityInfo T2 ON T0.CommodityId = T2.CommodityId
INNER JOIN CommoditySort T3 ON T2.SortId = T3.SortId
ORDER BY T3.SortID ASC, T2.CommodityID ASC

[

](https://www.51zxw.net/Show.aspx?cid=492&id=40098)[

](https://www.51zxw.net/Show.aspx?cid=492&id=40326)