再谈连接

外连接

之前的范例都是没有考虑条件可能无法为表中的所有行匹配的问题

左外连接与右外连接

SELECT a.account_id, a.cust_id, b.name FROM account a LEFT OUTER JOIN business b ON a.cust_id = b.cust_id;

外连接包括第一个表的所有行,但仅仅包含第二个表中那些匹配行的数据。关键字 left 指出连接左边的表决定结果集的行数,而右边只负责提供与之匹配的列值。因此,如果想要通过表 A 和 B 外连接得到结果为 A 中的所有行和 B 中匹配列的额外数据,则可以指定 A left outer join B 或者 B right outer join A。

三路外连接

SELECT a.account_id, a.product_cd, CONCAT(i.fname, ' ', i.lname) AS person_name, b.name AS business_name
FROM account a LEFT OUTER JOIN individual i ON a.cust_id = i.cust_id
LEFT OUTER JOIN business b ON a.cust_id = b.cust_id; --利用子查询限制查询中连接的数目
SELECT account_ind.account_id, account_ind.product_cd, account_ind.person_name, b.name AS business_name FROM
(SELECT a.account_id, a.product_cd, a.cust_id, CONCAT(i.fname, ' ', i.lname) AS person_name FROM account a
LEFT OUTER JOIN individual i ON a.cust_id = i.cust_id) account_ind LEFT OUTER JOIN business b ON account_ind.cust_id = b.cust_id; --这两个的结果一样

自外连接

SELECT e.fname, e.lname, e_mgr.fname AS mgr_fname, e_mgr.lname AS mgr_lname FROM employee e LEFT OUTER JOIN employee e_mgr
ON e.superior_emp_id = e_mgr.emp_id; SELECT e.fname, e.lname, e_mgr.fname AS mgr_fname, e_mgr.lname AS mgr_lname FROM employee e RIGHT OUTER JOIN employee e_mgr
ON e.superior_emp_id = e_mgr.emp_id;

上面的这两个例子所展示的结果明显不同,这仅仅是由改变一个关键字引起的,因此,我们在使用外连接时要确定到底使用左外连接还是右外连接。

交叉连接

如果想生成两个表的笛卡儿积,则需要指定交叉连接。

select pt.name, p.product_cd, p.name from product p, product_type pt;
或 select pt.name, p.product_cd, p.name from product p CROSS JOIN product_type pt;(官方建议的标准写法)

自然连接

所谓自然连接,是指依赖多表交叉时的相同列名来推断正确的连接条件。

例如,account 表包含了一个名为 cust_id 的列,它是来自 customer 表的外键,也是 customer 表的主键,我们可以使用自然连接编写一个查询来连接这两个表:

SELECT a.account_id, a.cust_id, c.cust_type_cd, c.fed_id FROM account a NATURAL JOIN customer c;

由于指定了自然连接,因此服务器检查表的定义并给两个表的连接添加了连接条件 a.cust_id = c.cust_id。

条件逻辑

简单的说,条件逻辑是程序执行时从多个路径中选取其一的能力。

case 表达式

查找型 case 表达式

语法如下:

CASE
WHEN C1 THEN E1
WHEN C2 THEN C2
...
WHEN CN THEN EN
[ELSE ED]
END

case 表达式可以返回任意类型的表达式,甚至包括子查询。

SELECT c.cust_id, c.fed_id,
CASE
WHEN c.cust_type_cd = 'I' THEN
(SELECT CONCAT(i.fname, ' ', i.lname) FROM individual i WHERE i.cust_id = c.cust_id)
WHEN c.cust_type_cd = 'B' THEN
(SELECT b.name FROM business b WHERE b.cust_id = c.cust_id)
ELSE 'Unknown'
END name
FROM customer c;

这个查询也可以用外连接,不过使用这个版本的话,服务器只有在需要时才从 individual 和 business 表中读取数据,而不会总是连接所有的表。

简单 case 表达式

语法:

CASE V0
WHEN V1 THEN E1
WHEN V2 THEN E2
...
WHEN VN THEN EN
[ELSE ED]
END

其实就是编程语言里面的 case 语法了。

事务

锁:锁是数据库服务器用来控制数据资源被并行使用的一种机制。当数据库的一些内容被锁定时,任何打算修改(或者可能是读取)这个数据的用户必须等到锁被释放。

锁的粒度:

  • 表锁:阻止多用户同时修改同一个表的数据。
  • 页锁:阻止多用户同时修改某表中同一页(一页通常是一段2~16KB的内存空间)的数据。
  • 行锁:阻止多用户同时修改某表中同一行的数据。

事务:它是一种将多条 SQL 语句聚集到一起,并且能够实现要么所有语句都执行,要么一个都不执行(这个属性称为原子性)。

启动事务

数据库服务器以下面两种方法之一创建事务:

  • 一个活跃事务总是和数据库会话相联系,所以没有必要,也没有什么方法能够显示地启动一个事务。当前事务结束时,服务器自动为会话启动一个新的事务。
  • 如果不显示地启动一个会话,单个的 SQL 语句会被独立于其他语句自动提交。启动一个事务之前需先提交一个命令。

结束事务

一旦事务启动,不管是通过 start transaction 命令显示地启动还是由数据库服务器隐式地启动,为了持久化数据变化都必须显示地结束事务。可以通过 commit 指令解决这个问题,该指令命令服务器将变化标记为永久性的,进而释放事务中使用的任何资源(也就是页锁或者行锁)。

如果打算撤销自事务启动时所发生的一切变化,读者必须提交 rollback 指令,它命令服务器将数据返回到处理前的状态。同样,会话使用的任何资源都会在 rollback 完成后被释放。

除了提交 commit 或 rollback 指令,结束事务还可以由其他情景触发,要么作为活动的间接结果,要么作为意外的结果:

  • 服务器宕机,在这种情况下,服务器重启时事务将会被自动回滚;
  • 提交一个SQL模式语句,比如 alter table,这将会引起当前事务提交和一个新事务的启动;
  • 提交另一个 start transaction 命令,将会引起前一个事务提交;
  • 如果服务器检测到一个死锁并且确定当前事务就是罪魁祸首,那么服务器就会提前结束当前的事务。这种情况下,事务将会被回滚,同时释放错误信息。

索引与约束

索引是寻找资源中特定项目的一种机制。

  • 创建索引:ALTER TABLE department ADD INDEX dept_name_idx (name);
  • 查看索引:SHOW INDEX FROM department;
  • 删除索引:ALTER TABLE department DROP INDEX dept_name_idx;
  • 唯一索引:ALTER TABLE department ADD UNIQUE dept_name_idx (name); --这里不需要为主键列创建索引,因为服务器已经为主键检查唯一性。
  • 多列索引:ALTER TABLE employee ADD INDEX emp_names_idx (lname, fname); --创建多列索引时,必须仔细考虑哪一列作为第一列,哪一列作为第二列等。
  • 索引类型:B树索引,位图索引,文本索引

如何使用索引

服务器通常首先利用索引快速定位特定表中的行,之后再访问相关表提取用户请求的补充信息。不过,如果索引包含满足查询的所有内容,那么服务器就不必访问相关表了。

索引的不足

每个索引事实上都是一个表,因此每次在对表添加或者删除行时,表中的索引必须被修改;当更新行时,受到影响的列的任何索引也必须被修改。因此,索引越多,服务器就需要做越多的工作来保持所有模式对象最新,这将会拖慢服务器处理任务的速度。另外,索引需要磁盘空间,同时也需要管理员耗费一些精力去管理它们。

约束

创建约束

CREATE TABLE product
(product_cd VARCHAR(10) NOT NULL,
name VARCHAR(50) NOT NULL,
product_type_cd VARCHAR(10) NOT NULL,
date_offered DATE,
date_retired DATE,
CONSTRAINT fk_product_type_cd FOREIGN KEY (product_type_cd) REFERENCES product_type (product_type_cd),
CONSTRAINT pk_product PRIMARY KEY (product_cd)
);

上面的这个表里包含了两个约束:一个指定了 product_cd 列作为表的主键,另一个指定了 product_type_cd 列作为来自 product_type 表的外键。

我们也可以先创建表再添加约束:

ALTER TABLE product
ADD CONSTRAINT pk_product PRIMARY KEY (product_cd); ALTER TABLE product
ADD CONSTRAINT fk_product_type_cd FOREIGN KEY (product_type_cd) REFERENCES product_type (product_type_cd);

删除主键约束或者外键约束:

ALTER TABLE product
DROP PRIMARY KEY; ALTER TABLE product
DROP FOREIGN KEY fk_product_type_cd;

约束与索引

创建约束有时可能导致自动创建一个索引,不过,数据库服务器对于约束和索引的关系有着不同的处理原则。在实施主键约束,外键约束和唯一约束时,MySQL 会生成新索引;SQL Server 只为主键约束和唯一约束生成新索引,不管外键约束。

级联约束

有了合适的外键约束后,如果想在子表插入新行或者修改行而导致父表中的外键列并无可匹配值,那么服务器会抛出一个错误;如果想删除或者修改一个父行,也会因为外键约束而抛出错误。那么这个时候,我们可以用级联约束命令服务器帮助自己将变化传播到所有子行,这样就保证了数据的完整性。on update cascade用来指定级联更新,on delete cascade用来指定级联删除。

ALTER TABLE product
ADD CONSTRAINT fk_product_type_cd FOREIGN KEY (product_type_cd)
REFERENCES product_type (product_type_cd)
ON UPDATE CASCADE
ON DELETE CASCADE;

有了这个版本的约束,当 product_type 表中的一行被更新时,服务器将更新 product 表中的子行,同样,如果 product_type 表中的行被删除,product 表中的子行也将被删除。

SQL学习指南第三篇的更多相关文章

  1. SQL学习指南第四篇

    SQL必知必会(第4版)学习笔记 插入数据 插入有几种方式: 插入完整的行 插入行的一部分 插入某些查询的结果(INSERT SELECT) 注意:省略列 如果表的定义允许,则可以在 INSERT 操 ...

  2. 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)

    从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://w ...

  3. Java工程师学习指南(中级篇)

    Java工程师学习指南 中级篇 最近有很多小伙伴来问我,Java小白如何入门,如何安排学习路线,每一步应该怎么走比较好.原本我以为之前的几篇文章已经可以解决大家的问题了,其实不然,因为我写的文章都是站 ...

  4. RabbitMQ学习总结 第三篇:工作队列Work Queue

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

  5. 学习KnockOut第三篇之List

    学习KnockOut第三篇之List 欲看此篇---------------------------------------------可先看上篇.          第一步,先搭建一个大概的框架起来 ...

  6. (转) 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)

    原文地址: http://www.cnblogs.com/lyhabc/p/4682986.html 这一篇是从0开始搭建SQL Server AlwaysOn 的第三篇,这一篇才真正开始搭建Alwa ...

  7. Java工程师学习指南(入门篇)

    Java工程师学习指南 入门篇 最近有很多小伙伴来问我,Java小白如何入门,如何安排学习路线,每一步应该怎么走比较好.原本我以为之前的几篇文章已经可以解决大家的问题了,其实不然,因为我之前写的文章都 ...

  8. Java工程师学习指南(初级篇)

    Java工程师学习指南 初级篇 最近有很多小伙伴来问我,Java小白如何入门,如何安排学习路线,每一步应该怎么走比较好.原本我以为之前的几篇文章已经可以解决大家的问题了,其实不然,因为我之前写的文章都 ...

  9. Java工程师学习指南(完结篇)

    Java工程师学习指南 完结篇 先声明一点,文章里面不会详细到每一步怎么操作,只会提供大致的思路和方向,给大家以启发,如果真的要一步一步指导操作的话,那至少需要一本书的厚度啦. 因为笔者还只是一名在校 ...

随机推荐

  1. 【学习笔记】【Design idea】一、Java异常的设计思想、性能相关、笔记

    1.前言: 异常.本该是多么优雅的东西,然而,得全靠自己在零散的信息中汇集. 学习笔记保持更新. 2.教材(参考资料) 其他 ①受检异常与非受检异常:https://www.cnblogs.com/j ...

  2. MySQL 基础知识梳理学习(一)----系统数据库

    information_schema 此数据库是MySQL数据库自带的,主要存储数据库的元数据,保存了关于MySQL服务器维护的所有其他数据库的信息,如数据库名.数据库表.表列的数据类型及访问权限等. ...

  3. MongoDB 3.6版本关于bind_ip设置

    2017年下半年新发布的MongoDB 3.6版本在安全性上做了很大提升,主要归结为两点: 1.将将bind_ip 默认值修改为了localhost: 2. 在db.createUser()和 db. ...

  4. 实战项目中Java heap space错误的解决

    部标GPS通讯系统在上线之后,经过不断调试,终于稳定运行一段时间,后来又遇到了Java heap space错误异常!日志如下: 说明系统中有未释放的对象.如何找出这些未释放对象以及监控JVM堆内存, ...

  5. 把exe注册为windows服务

    1.需要工具 Instsrv.exe(可以给系统安装和删除服务) Srvany.exe(可以让程序以服务的方式运行) 2.运行cmd,输入注册服务命令 "instsrv.exe完整路径&qu ...

  6. Boosting Static Representation Robustness for Binary Clone Search against Code Obfuscation and Compiler Optimization(二)

    接着上篇Asm2Vec神经网络模型流程继续,接下来探讨具体过程和细节. 一.为汇编函数建模  二.训练,评估   先来看第一部分为汇编函数建模,这个过程是将存储库中的每一个汇编函数建模为多个序列.由于 ...

  7. 如何设置非管理员用户配置特定的IIS站点

    如何设置非管理员用     户配置特定的IIS站点 一.           添加IIS管理服务 二.           启动管理服务 勾选启用远程连接后.点右边的应用 三.           设 ...

  8. PhpStorm 常用插件

    PhpStorm 插件 Dash : Dash 需要配合软件 Dash 使用. IdeaVim IdeaVim 对于习惯于使用 Vim 操作方式的人来说是个大福音. IdeaVim 也有默认配置, 可 ...

  9. SAP CRM Installed Bases(IBase)简介

    SAP CRM使用Installed Base(以下简称IBase)来组织服务相关对象并进行管理.因为我在最近的工作中经常接触这个概念,所以学习了一点相关文档.下面是文档的翻译. 本文链接:https ...

  10. 英语口语练习系列-C05-水电

    <登幽州台歌>·陈子昂 陈子昂(公元659-公元700年),唐代文学家,初唐诗文革新人物之一. Num 诗句 1 前不见古人, 2 后不见来者. 3 念天地之悠悠, 4 独怆然而涕下! T ...