SQL必知必会(第五版)学习笔记

文章目录

  • 第一课 了解SQL
    • 1.1数据库基础
      • 1.1.1 数据库(database)
      • 1.1.2 表(table)
      • 1.1.3 列和数据类型
      • 1.1.4 行(row)
      • 1.1.5 主键(primary key)
    • 1.2什么是SQL
  • 第二课 检索数据
    • 2.1 SELECT语句
    • 2.2 检索单个列
    • 2.3 检索多个列
    • 2.4 检索所有列
    • 2.5 检索不同的值
    • 2.6 限制结果
    • 2.7 注释
  • 第三课 排序检索数据
    • 3.1 排序数据
    • 3.2 按多个列排序
    • 3.3 按照相对列位置进行排序
    • 3.4 指定排序方向
  • 第四课 过滤数据
    • 4.1 使用WHERE 子句
    • 4.2 WHERE 子句操作符
      • 4.2.1 检查单个值
      • 4.2.2 不匹配检查
      • 4.2.3 范围值检查
        • 4.2.4 检查空值
  • 第五课 高级数据过滤
    • 5.1 组合 WHERE 子句
      • 5.1.1 AND 操作符
      • 5.1.2 OR 操作符
      • 5.1.3 求值顺序
      • 5.2 IN 操作符
      • 5.3 NOT 操作符
  • 第六课用通配符进行过滤
    • 6.1 LIKE 操作符
      • 6.1.1 百分号(%) 通配符
      • 6.1.2 下划线 (_) 通配符
  • 6.1.3 方括号 ([ ]) 通配符
  • 第七课创建计算字段
    • 7.1 计算字段
    • 7.2 拼接字段
    • 7.3 执行算术运算
  • 第八课 使用函数处理数据
    • 8.1使用函数
      • 8.1.1 文本处理函数
  • 第九课 汇总数据
    • 9.1 聚集函数
      • 9.1.1 AVG()函数
      • 9.1.2 COUNT()函数
      • 9.1.3 MAX() MIN()
    • 9.2 聚集不同值
  • 第十课 分组数据
    • 10.1 创建分组
    • 10.2 过滤分组
    • 10.3 SELECT子句顺序
  • 第十一课 使用子查询
    • 11.1 子查询
    • 11.2 利用子查询来进行过滤
    • 11.3 作为计算字段使用子查询
  • 第十二课 联结表
    • 12.1 联结
    • 12.2 创建联结
    • 12.2.1 WHERE子句的重要性
    • 12.2.2 内联结
    • 12.2.3 联结多个表
    • 课后挑战
  • 第十三课 创建高级联结
    • 13.1 使用表别名
    • 13.2 使用不同类型的联结
      • 13.2.1 自联结
    • 13.2.2 自然联结
    • 13.2.3 外联结
    • 13.2.4 使用带聚集函数的联结
    • 课后挑战
  • 第十四课 组合查询
    • 14.1 组合查询
    • 14.2 创建组合查询
      • 14.2.1 使用UNION
    • 14.2.2 UNION规则
    • 14.2.3 包含或取消重复的行
    • 14.2.4 对组合查询结果排序
  • 第十五课 插入数据
    • 15.1 插入数据
    • 15.1.1 插入完整的行
    • 15.1.2插入部分行
    • 15.1.3 插入检索出的数据
    • 15.2 从一个表复制到另一个表
  • 第十六课 更新和删除数据
    • 16.1 更新数据
    • 16.2 删除数据
  • 第十七课 创建和操纵表
    • 17.1 创建表
      • 17.1.1表创建基础
      • 17.1.2 使用NULL值
      • 17.1.3 指定默认值
    • 17.2 更新表
    • 17.3 删除表
    • 17.4 重命名表
  • 第十八课 使用视图
    • 18.1 视图
      • 18.1.1 为什么使用视图
      • 18.1.2 视图的规则和限制
    • 18.2 创建视图
      • 18.2.1利用视图来化简复杂的联结
      • 18.2.2 用视图重新格式化检索出来的数据
      • 18.2.3 使用视图过滤不想要的数据
      • 18.2.4 使用视图和计算字段
  • 第19课 使用存储过程
    • 19.1 存储过程
    • 19.2 为什么要使用存储过程
    • 19.3 执行存储过程
    • 19.4 创建存储过程
  • 第20课 管理事务处理
    • 20.1 事务处理
    • 20.2 控制事务处理
    • 20.2.1 使用 ROLLBACK
    • 20.2.2 使用COMMIT
    • 20.2.3 使用保留点
  • 第21课 使用游标
    • 21.1 游标
    • 21.2 使用游标
    • 21.2.1 创建游标
    • 21.2.2 使用游标
    • 21.2.3 关闭游标
  • 第22课 高级SQL特性
    • 22.1 约束
      • 22.1.1 主键
      • 22.1.2 外键
      • 22.1.3 唯一约束
      • 22.1.4 检查约束
    • 22.2 索引
    • 22.3 触发器

第一课 了解SQL

1.1数据库基础

1.1.1 数据库(database)

  • 数据库就是以某种有组织的方式存储的数据集合 (通俗来说)
  • 数据库(datdabase):保存有组织的数据的容器(通常是一个或一组文件)
  • 注意区别于DBMS 数据库管理软件 数据库database 是通过DBMS创建和操纵的容器

1.1.2 表(table)

  • 表: 某种特定类型数据的结构化清单
  • 说明使表名成为唯一的,实际上是数据库和表名等的组合; 也就是说,不同数据库里可以使用相同的表名

1.1.3 列和数据类型

  • 列(colomn):表中的一个字段.所有的表都是有一个或者多个列组成的

1.1.4 行(row)

  • 行(row):表中的一个记录,有时候也叫做数据库记录(record)

1.1.5 主键(primary key)

  • 主键(primary key): 一行或者几列,其值能够唯一标识表中的每一行
  • 主键列中的值不允许修改或更新
  • 主键值不能重用(如果某行从表中删除,它的主键不能赋值给以后的新行)

1.2什么是SQL

SQL是Struct Query Language(结构化查询语言)的缩写,SQL是一种专门与数据库沟通的语言

第二课 检索数据

2.1 SELECT语句

  • 关键字(keyword):作为SQL组成部分的保留字,关键字不能用作表或列的名字

2.2 检索单个列

例子:SELECT prod_name FROM Products;
上述语句利用SELECT语句从Products表中检索一个名为prod_name的列

-说明:

  • SELECT输出是没有经过排序的;
  • 多个SELECT语句必须以分号(;)分隔
  • SQL语句不区分大小写

2.3 检索多个列

  • 想要从一个表中检索多个列,仍然使用相同的SELECT语句,唯一不同的是必须再SELECT关键字后给出多个列名,
    列名之间使用逗号分隔

2.4 检索所有列

  • 使用SELECT * 语句可以检索所有列而不用列出

2.5 检索不同的值

使用 DISTINCT关键字,指示数据库返回不同的值

说明:

  • 必须放在列名的前面

  • 不能部分使用 DISTINCT,DISTINCT关键字作用域所有的列

2.6 限制结果

  • SQL server中使用SELECT时,可以用TOP关键字来限制最多返回多少行
    -SELECT TOP n colomn FROM tables;
  • DB2 中,使用FETCH FIRST N ROWS ONLY;
  • Oracle 基于ROWNUM 来计算行 WHERE ROWNUM ..
  • MySQL,MariaDB,PostgreSQL或者SQLite,需要使用LIMIT子句 LIMIT N
    也可以配合OFFSET语句使用,LIMIT N OFFSET M,从m+1 行开始找n行数据
    MySQL,MariaDB,SQLite 可以使用LIMIT M,N代替上述语句

2.7 注释

-常见的三种注释形式 -- # /* */,--#用于行内注释,/**/用于多行注释

第三课 排序检索数据

3.1 排序数据

  • 子句(clause):SQL语句是由子句构成的,有些是必需的,有些是可选的

  • 使用ORDER BY子句,取一个或者多个列的名字,据此对输出进行排序
    ** 注意**:
    1.ORDER BY 语句的位置必须是SELECT语句的最后一个子句
    2.可以使用非选择列进行排序

3.2 按多个列排序

使用多个列进行排序,依次比较,只有前面的列值相同才向后进行比较

3.3 按照相对列位置进行排序

OREDER BY NUM1.NUM2,NUM3
其中num1,num2,num3 都是已经选择的列的相对位置,没有选择的列不可以使用相对位置访问

3.4 指定排序方向

数据的排序默认使用升序排列

  • 如果要进行降序排列就要使用DECS 关键字
    注意:DECS关键字只应用于直接位于其前面的列名,如果想要在多个列上进行降序排列就要在每个列后面加上DESC关键字

第四课 过滤数据

4.1 使用WHERE 子句

在SELECT语句中,根据WHERE子句中指定的搜索条件进行过滤,WHERE子句在表名(FROM子句)之后给出

4.2 WHERE 子句操作符

SQL必知必会(第五版)学习笔记_第1张图片

4.2.1 检查单个值

语法:WHERE NAME = VALUE

4.2.2 不匹配检查

语法:WHERE NAME <> VALUE或者WHERE NAME != VALUE

4.2.3 范围值检查

语法:BETWEEN LOW AND HIGH

4.2.4 检查空值
  • NULL:无值(no value),它与字段包含0, 空字符串或者仅仅包含空格不同
  • WHERE IS NULL语句检查具有NULL值的列
  • NULL与非匹配:过滤具有指定值的所有行时,具有NULL值的行也不会返回

第五课 高级数据过滤

5.1 组合 WHERE 子句

操作符:用来联结或改变WHERE子句中的子句的关键字,也称逻辑操作符(logical operator)

5.1.1 AND 操作符

  • AND:用在WHERE 子句的关键字,用来检索所有满足给定条件的行

5.1.2 OR 操作符

  • OR:用在WHERE 子句中的关键字,用来检索匹配任一给定条件的行

5.1.3 求值顺序

  • AND 优先级比OR高,因此AND子句会被优先处理
  • 在需要优先执行OR子句的时候,可以加上圆括号进行明确分组,自定义运算顺序

5.2 IN 操作符

IN:WHERE子句中用来指定要匹配值的清单的关键字,功能与OR相当
语法:`IN(VALUE1,VALUE2,… )

5.3 NOT 操作符

NOT:WHERE子句中用来否定其后条件的关键字

第六课用通配符进行过滤

6.1 LIKE 操作符

通配符(wildcard):用来匹配值的一部分的特殊字符
搜索模式(search pattern):由字面值,通配符或者两者组合构成的搜索条件
在搜索子句中使用通配符,必须使用LIKE操作符

6.1.1 百分号(%) 通配符

最常使用的通配符是百分号%,在搜索串中,%表示任何字符出现任意次数。语法:LIKE 'word%'或者 LIKE '%word%'或者LIKE %word

6.1.2 下划线 (_) 通配符

(_)只匹配单个字符,而不是多个字符

6.1.3 方括号 ([ ]) 通配符

方括号([ ])通配符用来指定一个字符集 它必须匹配指定位置
例如:[JM]%[JM]匹配方括号中的任意一个字符,并且只能匹配单个字符

第七课创建计算字段

7.1 计算字段

字段(field):基本上与列意思相同,经常互换使,不过数据库列一般称为列,而字段这个术语通常在提到计算字段使用

7.2 拼接字段

拼接(concatenate):将值联结到一起(将一个值附加到另一个值)构成单个值

  • 根据使用的DBMS,可以有三种方式:
  1. + 例子:SELECT vend_name + '(' + vend_country + ')' FROM Vendors ORDER BY vend_name
  2. || 例子: SELECT vend_name || '(' || vend_country || ')' FROM Vendors ORDER BY vend_name
  3. Concat()函数 例子:SELECT Contact(vend_name ,'(' , vend_country ,')') FROM Vendors ORDER BY vend_name
    而输出的计算字段的两个列会用空格填充,需要使用在联结的列前使用TRIM函数

TRIM函数:大多数DBMS都支持RTRIM()(去掉字符串右边的所有空格),和LTRIM()(去掉字符串左边的所有空格)
以及TRIM()(去掉两边所有的空格)

使用别名:别名是一个字段或者值的替换名,别名用AS关键字赋予,并且真实创建了别名列,也叫导出列(derived column)

7.3 执行算术运算

第八课 使用函数处理数据

8.1使用函数

大多数DBMS支持的函数:

  • 用于处理文本字符串
  • 用于在数值上进行算数操作
  • 用于处理日期和时间值并从这些值中提取特定成分
  • 用于生成美观好懂的输出内容的格式化函数
  • 返回DBMS正在使用的特殊信息

8.1.1 文本处理函数

Left()函数:返回string字符串左边n个字符

Right()函数:返回string字符串右边n个字符

Lower()函数:大写字符转化成小写的函数

Upper()函数:小写字符转化成大写的函数

Len()/Length()函数:返回文本字段中值的长度

Substr()/Substring()函数:截取字符串中的一部分字符

Charindex()函数:返回需要查询的字符串的位置

LTRIM()函数:删除数据中左边的空格

RTRIM()函数:删除数据中右边的空格

TRIM()函数:删除数据中的空格

REPLACE()函数:替换文本中特定的字符串

第九课 汇总数据

9.1 聚集函数

常用sql聚集函数:

AVG() :返回某列的平均值

COUNT(): 返回某列的行数

MAX():返回某列的最大值

MIN():返回某列的最小值

9.1.1 AVG()函数

只能用于确定特定数值列的平均值,而且列名必须作为函数参数给出

9.1.2 COUNT()函数

  • 使用count(*)对表中的行数进行计数,不管表列中包含的是空值还是非空值
  • 使用COUNT(column)对特定列中具有值的行进行计数,忽略NULL值

9.1.3 MAX() MIN()

对非数值数据使用MAX()或者MIN(),返回该列排序后的最后(前)一行

9.2 聚集不同值

  • 对所有行执行运算,指定ALL参数或者不指定参数
  • 只包含不同的值,指定DISTINCT参数
    注意: DISTINCT不能用于COUNT(*)

第十课 分组数据

10.1 创建分组

例子:SELECT vend_id,COUNT(*) AS num_prods FROM Products GROUP BY vend_id;

  • GROUP BY 子句可以抱哈任意数目的列,可以对分组进行嵌套
  • 如果GROUP BY 子句中嵌套了分组,数据将在最后指定的分组上进行汇总
  • GROUP BY 子句中列出的每一列都必须是检索列或者有效的表达式,不能使用别名
  • 如果分组列中含有NULL值的行,则NULL将作为一个分组返回
  • GROUP BY 子句必须出现在SELECT之后,ORDER BY之前

10.2 过滤分组

使用HAVING 进行过滤分组,在分组之后进行过滤,结合GROUP BY 使用

10.3 SELECT子句顺序

SELECT FROM WHERE GROUP BY HAVING ORDER BY

第十一课 使用子查询

11.1 子查询

子查询 也就是嵌套在其他查询里面的查询

11.2 利用子查询来进行过滤

作为子查询的select语句只能查询单个列

11.3 作为计算字段使用子查询

例如:SELECT cust_name ,cust_state,(SELECT COUNT(*) FROM Orders WHERE Orders.cust_id = Customers.cust_id) AS orders FROM Customers ORDER BY cust_name
记住要完全限定列名当查询的多个表中有相同名字的列时。

第十二课 联结表

12.1 联结

联结是一种机制,用来在一条SELECT语句中关联表

12.2 创建联结

指定要联结的所有表以及关联它们的方式即可 例子:SELECT vend_name,prod_name,prod_price FROM Vendors,Products WHERE Vendors.vend_id = Products.vend_id

12.2.1 WHERE子句的重要性

笛卡尔积:由没有联结关系的表关系返回的结果是笛卡尔积,检索出的行的数目将是第一个表中的行数乘以第二个表中的行数(返回笛卡尔积的联结也叫做叉联结)
所以使用Where子句是十分必要的,不然就会返回笛卡尔积作为查询结果

12.2.2 内联结

目前使用的联结称为等值联结,它基于两个表之间的相等测试,这种联结也称作内联结。其实也可以用关键字INNER JOIN,联结条件用ON给出,而不是简单的Where子句,来表命联结的类型。
例子:SELECT vend_id ,prod_id,prod_price FROM Vendors INNER JOIN Products ON Vendors.vend_id = Products.vend_id;

12.2.3 联结多个表

例子:SELECT prod_name,vend_name,prod_price,quantity FROM OrderItems,Products,Vendors WHERE Products.vend_id= Vendors.vend_id AND OrderItems.prod_id =Vendors.vend_id AND Order_num =20007;

课后挑战

1.编写SQL语句,返回Customers表中的顾客名称(cust_name)和Orders表中的相关订单号(order_num),并按顾客名称再按订单号对结果进行排序,实际上是尝试两次,一次使用简单的等值连接语法
答案:
1.SELECT cust_name,order_num
FROM Customers,Orders
WHERE Customers.cust_id=Orders.cust_id
ORDER BY cust_name,order_num;
2.SELECT cust_name, order_num
FROM Customers
INNER JOIN Orders
ON Customers.cust_id = Orders.cust_id
ORDER BY cust_name, order_num;

2.在上一题的基础上添加第三列OrderTotal,其中包含每个订单的总价,可以使用OrderItem表的子查询创建OrderTotal列,或者将OrderItems表与现有表联结并使用聚合函数。
答案:
1.SELECT cust_name, order_num,
(SELECT Sum(item_price*quantity)
FROM OrderItems
WHERE Orders.order_num=OrderItems.order_num) AS OrderTotal
FROM Customers, Orders
WHERE Customers.cust_id = Orders.cust_id
ORDER BY cust_name, order_num;
2.SELECT cust_name, Orders.order_num, Sum(item_price*quantity) AS OrderTotal
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id=Orders.cust_id AND Orders.order_num = OrderItems.order_num
GROUP BY cust_name, Orders.order_num
ORDER BY cust_name, order_num;
3.编写SQL语句,检索订购的产品BR01的日期,使用联结和简单的等值联结语法
答案:SELECT cust_id, order_date
FROM Orders, OrderItems
WHERE Orders.order_num = OrderItems.order_num
AND prod_id = 'BR01'
ORDER BY order_date;

4.返回购买prod_id为BR01的产品的所有顾客的电子邮件(Customers表中的cust_email)使用两个INNER JOIN语句,并且用WHERE子句进行过滤。
答案:SELECT cust_email
FROM Customers
INNER JOIN Orders ON Customers.cust_id = Orders.cust_id
INNER JOIN OrderItems ON Orders.order_num = OrderItems.order_num
WHERE prod_id = 'BR01';

5.使用联结从Customers表返回顾客名称(cust_name),并从OrderItems表中返回所有订单的总价
答案:
1.SELECT cust_name, SUM(item_price*quantity) AS total_price
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id = Orders.cust_id
AND Orders.order_num = OrderItems.order_num
GROUP BY cust_name HAVING SUM(item_price*quantity) >= 1000
ORDER BY cust_name;
2.SELECT cust_name, SUM(item_price*quantity) AS total_price
FROM Customers
INNER JOIN Orders ON Customers.cust_id = Orders.cust_id
INNER JOIN OrderItems ON Orders.order_num = OrderItems.order_num
GROUP BY cust_name
HAVING SUM(item_price*quantity) >= 1000
ORDER BY cust_name;

第十三课 创建高级联结

13.1 使用表别名

使用表别名的好处:

1.缩短SQL语句
2.允许在一条SQL语句中多次使用相同的表

例子:.SELECT cust_name, order_num
FROM Customers AS C,Orders AS O
WHERE C.cust_id = O.cust_id
ORDER BY cust_name, order_num;

13.2 使用不同类型的联结

13.2.1 自联结

查询和Jim Jones一个公司的所有员工

使用子查询:
例子:SELECT cust_id,cust_name,cust_contact
FROM Customers
WHERE cust_name = ( SELECT cust_name
FROM Customers
WHERE cust_contact = 'Jim Jones');

使用自联结
SELECT c1.cust_id,c1.cust_name,c1.cust_contact
FROM Customers AS c1,Customers AS c2
WHERE c1.cust_name=c2.cust_name AND c2.cust_contact ='Jim Jones';

13.2.2 自然联结

自然联结排除多次出现,使每一列只返回一次。

SELECT C.*,Order.order_num,O.order_date,
OI.prod_id,OI.quantity,OI.item.price
FROM Customers AS C,Orders AS O,OrderItems AS OI
WHERE C.cust_id =O.cust_id
AND OI.order_num = O.order_num
AND prod_id = 'RGAN01'

13.2.3 外联结

外联结有三种基本类型:左外联结(LEFT OUTER JOIN)和右外联结(RIGHT OUTER JOIN),全外联结(FULL OUTER JOIN) 。
左外联结和右外联结分别包含左表(右表)的不关联行,全外联结包含两个表不关联的行。

13.2.4 使用带聚集函数的联结

例子:SELECT Customers.cust_id,
COUNT(Orders.prder_num) AS num_ord
FROM Customers
INNER JOIN Orders ON Customers.cust_id = Orders.cust_id
GROUP BY Customers.cust_id

课后挑战

第十四课 组合查询

14.1 组合查询

SQL允许执行多个查询,并将结果作为一个查询结果集返回,这些组合查询通常称为union(并)查询或者复合查询(compound query)

14.2 创建组合查询

使用UNION操作符来组合数条SQL查询,将结果组合成一个结果集。

14.2.1 使用UNION

在每条SELECT语句之间放上关键字UNION
例子:SELECT cust_name,cust_contact,cust_email
FROM Customers
WHERE cust_state IN ('IL','IN','MI')
UNION
SELECT cust_name,cust_contact,cust_email
FROM Customers
WHERE cust_name = 'Fun4ALL'

14.2.2 UNION规则

UNION语句必须由两条或者两条以上的SELECT语句组成,语句之间用关键字UNION分隔
UNION中的查询必须包含相同的列,表达式或聚集函数
列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含转换的类型

UNION的列名:
如果遇到不一样的名字,默认返回第一个名字,第二个名字可以是第一个列的别名,查询结果中只有(返回)第一个名字

14.2.3 包含或取消重复的行

union默认去除重复的行,如果想返回所有的行,可以使用UNION ALL

14.2.4 对组合查询结果排序

ORDER BY 子句必须在最后面,也就是说只允许一种排序方式

其他类型的UNION:EXCEPT可以用于检索只存在于第一个表的数据,INTERSECT可以检索两个表中都存在的数据

第十五课 插入数据

15.1 插入数据

使用INSERT插入数据,可以分为三种,插入完整的行,插入行的一部分,插入某些查询的结果

15.1.1 插入完整的行

例子:
INSERT INTO Customers
VALUES(100000006
'Toy Land',
'123 Any Street',
'New York',
'NY',
'1111',
'USA',
NULL,
NULL

这种插入方式的赋值是按列的固定顺序来进行的,并不安全

推荐使用另一种方式(如下)
INSERT INTO Customers(
cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country,
cust_contact,
cust_email
)
VALUES(100000006
'Toy Land',
'123 Any Street',
'New York',
'NY',
'1111',
'USA',
NULL,
NULL

15.1.2插入部分行

省略列:在使用Insert插入时可以允许部分列省略,那些列允许NULL值(无值或者空值)或者在表中定义中给出默认值

15.1.3 插入检索出的数据

使用INSERT SELECT
例子:
INSERT INTO Customers(
cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country,
cust_contact,
cust_email
)
SELECT
cust_id,
cust_name,
cust_address,
cust_city,
cust_state,
cust_zip,
cust_country,
cust_contact,
cust_email
FROM CustNew;

15.2 从一个表复制到另一个表

使用CREATE SELECT语句将一个表的内容复制到另一个表中。

CREATE TABLE CustCopy AS SELECT * FROM Customers;

使用SQLServer:
SELECT * INTO CustCopy FROM Customers;

select into 使用时:

  • 任何select 选项和子句都可以使用,包括GROUP BY 和 WHERE
  • 可以利用联结从多个表中插入数据
  • 数据只能插入到一个表中

第十六课 更新和删除数据

16.1 更新数据

使用update语句更新(修改)表中的数据:

  • 更新特定行
  • 更新所有行(不使用where子句加以限制)
    基本的UPDATE语句由三部分组成:
  • 要更新的表
  • 列名和它们的新值
  • 确定要更新哪些行的过滤条件

例子:
UPDATE Customers
SET cust_email = '[email protected]'
WHERE cust_id = 1000000005;

更新更多列的操作:
例子:UPDATE Customers
SET cust_email = '[email protected]',
cust_email = Sam Roberts
WHERE cust_id = 1000000005;

UPDATE语句可以使用子查询
要删除某一列的值,你可以设置它为NULL

16.2 删除数据

DELETE 语句:

  • 删除特定行
  • 删除全部行(不使用where限制)

删除一行数据
例子:DELETE FROM Customers
WHERE cust_id = 1000000006;

如果有外键的存在,delete语句会抛出错误并终止

FROM关键字是可选的,但是为了可移植性,我们通常保留

第十七课 创建和操纵表

17.1 创建表

一般创建的方式有两种:

  • 多数DBMS都具有交互式创建和管理数据库表的工具
  • 表也可以直接使用SQL语句操纵

17.1.1表创建基础

使用CREATE TABLE创建表:

  • 新表的名字,在关键字CREATE TABLE 之后给出
  • 表列的名字和定义,用逗号分隔
  • 有的DBMS还要求指定表的位置
    例子:创建本书中的Products表:
    CREATE TABLE Products
    (
    prod_id CHAR(10) NOT NULL,
    vend_id CHAR(10) NOT NULL,
    prod_name CHAR(254) NOT NULL,
    prod_price DECIMAL(8,2) NOT NULL,
    prod_desc VARCHAR(1000) NULL
    );

在创建新的表时,指定的表必须不存在,否则会出错。

17.1.2 使用NULL值

每个表要么是NULL值要么是非NULL值,根据创建时表的定义决定。

17.1.3 指定默认值

  • 指定默认值,再插入行时如果不给出值,DBMS将自动采取默认值。
  • 默认值在CREATE TABLE语句的列定义中用关键字DEFAULT指定。
  • 默认值经常用于日期或者时间戳列。
    MQSQL用户使用CURRENT_DATE(),Oracle用户使用SYSDATE(),SQL server 用户指定GETDATE()。

17.2 更新表

ALTER TABLE 语句,虽然所有的DBMS都支持ALTER TABLE,但它们所允许更新的内容差别很大。

给已有表增加列时所有DBMS都支持的唯一操作,
例子:ALTER TABLE Vendors
ADD vend_phone CHAR(20);

复杂的表结构更改一般需要手动删除过程:

  • 使用新的布局创建一个新表
  • 使用INSERT SELECT 语句从旧表赋值数据到新表
  • 检验包含所需数据的新表
  • 重命名旧表
  • 用旧表原来的名字重命名新表
  • 根据需要,重新创建触发器,存储过程,索引和外键

17.3 删除表

DROP TABLE 语句
DROP TABLE CustCopy;

17.4 重命名表

每个DBMS对表重命名的支持有所不同 ,DB2,MariaDB,MySQL,Oracle,PostgreSQL使用RENAME语句,SQL server使用sp_rename存储过程,SQLite使用ALTER TABLE语句。

第十八课 使用视图

18.1 视图

视图是虚拟的表,只包含动态检索数据的查询
例子:SELECT cust_name,cust_contact
FROM Customers ,Orders,OrderItems
WHERE Customers.cust_id = Orders.cust_id
AND OrderItems.order_num = Orders.order_num
AND prod_id='RGAN01';

使用视图
SELECT cust_name,cust_contact
FROM ProductCustomers
WHERE prod_id='RGAN01';

18.1.1 为什么使用视图

常见应用:

  • 重用SQL语句
  • 简化复杂的查询操作
  • 使用表的一部分
  • 保护数据
  • 更改数据格式和表示

18.1.2 视图的规则和限制

常见的限制:

  • 与表一样,视图必须唯一命名
  • 对于可以创建的视图数目没有限制
  • 创建视图必须提供足够的权限
  • 视图可以嵌套,即可以利用从其他视图中检索数据的查询来构造视图
  • 许多DBMS禁止视图使用ORDER BY 语句
  • 有些DBMS要求对所有视图返回的列进行命名
  • 视图不能使用索引
  • 有些DBMS把视图作为只读的查询

18.2 创建视图

CREATE VIEW 语句来创建,与CREATE TABLE语句一样,CREATE VIEW只能用于创建不存在的视图

18.2.1利用视图来化简复杂的联结

视图最常见的应用就是隐藏复杂的SQL,这通常涉及联结
例子:
CREATE VIEW
SELECT cust_name,cust_contact
FROM Customers ,Orders,OrderItems
WHERE Customers.cust_id = Orders.cust_id
AND OrderItems.order_num = Orders.order_num
AND prod_id='RGAN01';

使用视图
SELECT cust_name,cust_contact
FROM ProductCustomers
WHERE prod_id='RGAN01';

18.2.2 用视图重新格式化检索出来的数据

例子:SELECT RTRIM(vend_name)+'('+RTRIM(vend_country)+')'
AS vend_title
FROM Vendors
ORDER BY vend_name

CREATE VIEW
SELECT RTRIM(vend_name)+'('+RTRIM(vend_country)+')'
AS vend_title
FROM Vendors

SELECT * FROM VendorLocations;

18.2.3 使用视图过滤不想要的数据

例子:CREATE VIEW CustomerEMailList AS
SELECT cust_id,cust_name,cust_email
FROM Customers
WHERE cust_email IS NOT NULL;

18.2.4 使用视图和计算字段

例子:CREATE VIEW OrderItemExpanded AS
SELECT prod_id,
quantity,
item_price
quantity * item_price AS expanded_price
FROM OrderItems

第19课 使用存储过程

19.1 存储过程

创建存储过程,简单的来讲就是,为以后使用保存的一条或者多条SQL语句,可以讲其视为批文件。

19.2 为什么要使用存储过程

  • 通过把处理封装在一个易用的单元,可以简化复杂的操作。
  • 保证了数据的一致性
  • 简化对变动的管理
  • 更加安全

19.3 执行存储过程

使用EXCUTE关键字,EXCUTE接收存储过程名和需要传递给它的任何参数。
例子:EXCUTE AddNewProduct('JTS01',
'Stuffed Effiel Tower',
'6.49',
'Plush stuffed toy with the text Tour Eiffel in red white and blue' );

19.4 创建存储过程

Orcle 版本:
CREATE PROCEDURE MailingListCount (
ListCount OUT INTEGER)
IS
v_rows INTERGER;
BEGIN
SELECT COUNT(*) INTO v_rows
FROM Customers
WHERE NOT cust_email IS NULL;
ListCount := v_rows;
ENDS;

该存储过程有一个参数ListCount,此参数从存储过程返回一个值而不是传递一个值给存储过程。OUT用来指示这种行为。
Oracle 支持IN(传递值给存储过程),OUT(从存储过程返回值,如这里),INOUT(既传递值给存储过程也从存储过程返回值)三个参数。

调用(Oracle)例子:
var ReturnValue NUMBER
EXEC MailingListCount(:ReturnValue);
SELECT ReturnValue;
声明ReturnValue 保存存储过程返回的所有值,然后执行过程,最后使用SELECT语句显示返回值

SQL Server版本
CREATE PROCEDURE MailingListCount
AS
DECLARE @cnt INTEGER
SELECT @cnt = COUNT(*)
FROM Customers
WHERE NOT cust_email IS NULL;
RETURN @ cnt;

@cnt是一个局部变量,然后再SELECT语句中使用这个变量,让它包含COUNT()函数返回的值,最后RETURN @cnt 语句计数返回给调用程序。

调用:
DECLARE @ReturnValue INT
EXECUTE @ReturnValue=MailingListCount;
SELECT @ReturnValue;

例子:CREATE PROCEDURE NewOrder @cust_id CHAR(10)
AS
--为这个订单号声明一个变量
SELECT @order_num = MAX(order_num)
FROM Orders
--决定下一个订单号
SELECT @order_num =@order_num+1
--插入新订单
INSERT INTO Orders(order_num,order_date,cust_id)
VALUES(@order_num,GETDATE(),@cust_id)
--返回订单号
RETURN @order_num;
为Orders表创建一个新订单,只有一个参数,下一个顾客的ID,订单号和日期自动生成。

CREATE PROCEDURE NewOrder @cust_id CHAR(10)
AS
--插入新订单
INSERT INTO Orders(cust_id)
VALUES(@cust_id)
--返回订单号
SELECT order_num = @@IDENTITY;
借助SQLSever 的自动增量列,生成order_num,并使用@@IDENTITY获取

第20课 管理事务处理

20.1 事务处理

事务处理(transaction processing):确保成批的操作要么完全执行,要么完全不执行
事务(transaction):指一组SQL语句
回退(rollback):撤销指定SQL语句的过程
提交(commit):指将未存储的SQL语句结果写入数据库表;
保留点(savepoint):指事务处理中设置的临时占位符(placeholder),可以对它发布回退

20.2 控制事务处理

SQL Server:
BEGIN TRANSACTION
....
COMMIT TRANSACTION

MariaDB MYSQL:
START TRANSACTION
....

Oracle:
START TRASACTION
...

PostgreSQL
BEGIN
...

20.2.1 使用 ROLLBACK

DELETE FROM Orders;
ROLLBACK;

20.2.2 使用COMMIT

SQL Server:
BEGIN TRANSACTION
DELETE OrderItems WHERE order_num =12345
DELETE Orders WHERE order_num = 12345
COMMIT TANSACTION

Oracle:

SET TANSACTION
DELETE OrderItems WHERE order_num =12345;
DELETE Order_num=12345
COMMIT;

20.2.3 使用保留点

MariaDB,MySQL,Oracle中创建占位符:
SAVEPOINT xxxx
ROLLBACK TO delete1
SQL Server中:
SAVE TRANSACTION delete1;
ROLLBACK TRANSACTION delete1
定义保留点,配合rollback语句回退到该点

第21课 使用游标

21.1 游标

游标(cursor)是一个存储在DBMS服务器上的数据库查询,它不是一条SELECT语句,而是被该语句检索出来结果集。
游标的常见特性:

  • 可以标记为只读
  • 可以控制可以执行的定向操作(向前,向后,第一,最后,绝对位置,相对位置等等)
  • 可以标记某些列为可编辑的
  • 规定范围,使游标对创建它的请求或者对所有请求可访问
  • 指示出DBMS对检索的数据进行复制,是数据在游标打开和访问时不变化

21.2 使用游标

  • 使用前必须声明,声明后必须使用,使用后必须关闭

21.2.1 创建游标

MariaDB,MySQL,DB2,SQL Server版本
DECLARE CustCursor CURSOR
FOR
SELECT * FROM Customers
WHERE cust_email IS NULL;

Oracle,PostgreSQL版本:
DECLARE CURSOR CustCursor
IS
SELECT * FROM Customers
WHERE cust_email IS NULL;

21.2.2 使用游标

OPEN CURSOR CustCursor

使用FETCH从游标中检索第一行(Oracle)
DECLARE TYPE CustCursor IS REF CURSOR
RETURN Customers%ROWTYPE;
DECLARE CustRecord Customers%ROWTYPE
BEGIN
OPEN CustCursor
FETCH CustCursor INTO CustRecord;
CLOSE CustCursor;
END;

检索所有行
DECLARE TYPE CustCursor IS REF CURSOR
RETURN Customers%ROWTYPE;
DECLARE CustRecord Customers%ROWTYPE
BEGIN
OPEN CustCursor
LOOP
FETCH CustCursor INTO CustRecord;
EXIT WHEN CustCursor%NOTFOUND;
END LOOP
CLOSE CustCursor;
END;

21.2.3 关闭游标

CLOSE CustCursor
Microsoft SQL Server:
CLOSE CustCursor
DEALLOCATE CURSOR CustCursor

第22课 高级SQL特性

22.1 约束

约束(constraint):管理如何插入数据或处理数据库的规则

22.1.1 主键

主键是一种特殊的约束,保证一列的值唯一且永不改动
使用PRIMARY KEY关键字,定义主键:
CREATE TABLE Products
(
prod_id CHAR(10) NOT NULL PRIMARY KEY,
vend_id CHAR(10) NOT NULL,
prod_name CHAR(254) NOT NULL,
prod_price DECIMAL(8,2) NOT NULL,
prod_desc VARCHAR(1000) NULL
);

或者:
ALTER TABLE Porducts
ADD CONTRAINT PRIMARY KEY (vend_id);

22.1.2 外键

外键是表中的一列,其值必须在另一个表的主键中。外键是保证引用完整性的极其重要的部分。
例子:
CREATE TABLE Orders( order_num INTERGER NOT NULL PRIMARY KEY, order_date DATETIME NOT NULL, cust_id CHAR(10) NOT NULL REFERENCES Customers(cust_id))

同样可以使用CONSTRAINT语法来完成
ALTER TABLE Orders
ADD CONSTRAINT
FOREIGN KEY (cust_id)REFERENCE Customers(cust_id);

22.1.3 唯一约束

唯一约束用来保证表中的数据是唯一的,类似于主键

区别:

  • 可以包含多个唯一约束,但是只能有一个主键
  • 唯一约束可以包含NULL值
  • 唯一约束列可以更新或者修改
  • 可重复使用
  • 唯一约束不能用来定义外键

可以使用UNIQUE关键字来定义唯一约束

22.1.4 检查约束

检查约束用来保证一列或者(一组列中的数据满足一组指定的条件)

常见用途:

  • 检查最大值和最小值
  • 指定范围
  • 只允许特定的值

在创建表时 CHECK
CREATE TABLE Products
(
prod_id CHAR(10) NOT NULL PRIMARY KEY,
vend_id CHAR(10) NOT NULL CHECK(...),
prod_name CHAR(254) NOT NULL,
prod_price DECIMAL(8,2) NOT NULL,
prod_desc VARCHAR(1000) NULL
);
使用constraint语法
ADD CONSTRAINT CHECK (gender LIKE ‘[MF]’);

22.2 索引

索引用来排序数据以加快搜索和排序操作的速度

索引的特性:

  • 改善检索的性能
  • 可能要占据 大量内存空间
  • 并非所有数据都适合做索引
  • 用于数据过滤和数据排序
  • 可以在索引中定义多个列

使用CREATE INDEX创建
例子:
CREATE INDEX prod_name_ind
ON Porducts (prod_name);

22.3 触发器

触发器是特殊的存储过程,它在特定的数据库活动发生时自动执行,触发器可以和特定表上的INSERT,UPDATE,DELETE(或组合)相关联。

触发器内的代码有以下数据的访问权:

  • INSERT 操作中的所有新数据
  • UPDATE操作中的所有新数据和旧数据
  • DELETE操作中所有删除的数据
    常见用途:
  • 保证数据一致
  • 基于某个表的变动在其他表上执行活动
  • 进行额外的验证并根据需要回退数据
  • 计算计算列的值或者更新时间戳
    例子:
    CREATE TRIGGER customer_state
    ON Customers
    FOR INSERT,UPDATE
    AS
    UPDATE Customers
    SET cust_state = upper(cust_state)
    WHERE Customers.cust_id = inserted.cust_id;

未完待续…

你可能感兴趣的:(入门笔记,sql)