再谈连接

外连接

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

左外连接与右外连接

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. nginx 防止盗链

    1.测试盗链(www.html2.com 盗取 www.html5.com的图片) 2.防止盗链 符合盗链 —— 重写 说明:if ($invalid_referer) {,if的后面是有空格的,如果 ...

  2. Redis(十一):Redis的事务功能详解

    相关命令 1. MULTI 用于标记事务块的开始.Redis会将后续的命令逐个放入队列中,然后才能使用EXEC命令原子化地执行这个命令序列. 这个命令的运行格式如下所示: MULTI 这个命令的返回值 ...

  3. XML详解二XML的解析与创建

    XML用来传输和存储数据,如何解析获取到的XML文本呢? 一.解析XML 创建demo.xml文件: <?xml version="1.0" encoding="U ...

  4. LeetCode算法题-Find Mode in Binary Search Tree(Java实现)

    这是悦乐书的第246次更新,第259篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第113题(顺位题号是501).给定具有重复项的二叉搜索树(BST),找到给定BST中的 ...

  5. 【Python 25】52周存钱挑战5.0(datetime库和import)

    1.案例描述 按照52周存钱法,存钱人必须在一年52周内,每周递存10元.例如,第一周存10元,第二周存20元,第三周存30元,直到第52周存520元. 记录52周后能存多少钱?即10+20+30+. ...

  6. linux 本机内核模块

    make -C /lib/modules/4.13.0-36-generic/build M=/$(pwd) modules 内核里只需要写obj-m:=hello.o

  7. uml类图关系

    原文地址http://www.jfox.info/uml-lei-tu-guan-xi-fan-hua-ji-cheng-shi-xian-yi-lai-guan-lian-ju-he-zu-he 在 ...

  8. 监控glusterfs

    监控集群状态 [4ajr@elk1 scripts]$ cat glusterfs_peer_status.sh #!/bin/bash peer_status=`sudo gluster peer ...

  9. springboot为导出的pdf和excel加水印

    相信很多小伙伴们在做导出pdf或者excel文件时会被要求在文件上加上水印,本篇博客就来讲讲如何为pdf和excel加水印. 导出pdf加水印 其实在导出pdf时加上水印并不难,因为itext提供了添 ...

  10. SQL的一些基础查询语法

     基础.限定.模糊查询     关键字都是大写. 使用 BETWEENN AND 的时候小的数字或者日期放到  AND(并且)  的面前,大的一个放到AND 后面.   数据操纵语言SQL分类(DML ...