SQL必知必会(第3版)学习笔记【11-15章】

版权声明:本文为博主 http://blog.csdn.net/churximi 原创文章,未经允许不得转载,谢谢。 https://blog.csdn.net/churximi/article/details/51586861

第11章 使用子查询

子查询

  • 子查询(subquery):嵌套在其他查询中的查询

利用子查询进行过滤

  • 可以把一条SELECT语句返回的结果用于另一条SELECT语句的WHERE子句
  • 也可以使用子查询来把3个查询组合成一条语句
SELECT cust_id 
FROM Orders 
WHERE order_num IN (SELECT order_num 
                    FROM OrderItems 
                    WHERE prod_id = 'RGAN01');

作为计算字段使用子查询

  • 使用子查询的另一方法是创建计算字段

第12章 联结表

  • 各表通过某些常用的值(即关系设计中的关系(relational))互相关联
  • 分解数据为多个表能更有效地存储,更方便地处理,并且具有更强大的可伸缩性

使用联结

  • 通过联结来用单条SELECT语句检索出数据
  • 联结是一种机制,用来在一条SELECT语句中关联表
  • 联结在实际的数据库表中不存在,它不是物理实体

创建联结

SELECT vend_name, prod_name, prod_price 
FROM Vendors, Products 
WHERE Vendors.vend_id = Products.vend_id;
  • 单条SELECT语句返回两个(多个)不同表中的数据

WHERE子句的重要性

  • 在一条SELECT语句中关联几个表时,相应的关系是在运行中构造的
  • 在联结两个表时,实际上做的是将第一个表中的每一行与第二个表中的每一行配对
  • 应该保证所有联结都有WHERE子句,否则将返回很多不正确的数据

笛卡尔积

  • 由没有联结条件的表关系返回的结果为笛卡尔积,检索出的行的数目将是第一个表中的行数乘以第二个表中的行数
  • 也称为叉联结(cross join)

内部联结(等值联结)

SELECT vend_name, prod_name, prod_price 
FROM Vendors INNER JOIN Products 
ON Vendors.vend_id = Products.vend_id;

联结多个表

SELECT prod_name, vend_name, prod_price, quantity 
FROM OrderItems, Products, Vendors 
WHERE Products.vend_id = Vendors.vend_id 
    AND OrderItems.prod_id = Products.prod_id 
    AND order_num = 20007;
  • 不要联结不必要的表,以免造成性能下降

第13章 创建高级联结

使用表别名

  • 缩短SQL语句
  • 允许在单条SELECT语句中多次使用相同的表
SELECT cust_name, cust_contact 
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';

使用不同类型的联结

  • 内部联结(等值联结)
  • 自联结
  • 自然联结
  • 外部联结

自联结

  • 自联结通常作为外部语句来代替从相同表中检索数据的使用子查询语句
  • 许多DBMS处理联结远比处理子查询快得多
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';

自然联结

  • 自然联结排除多次出现的列,每个列只返回一次
  • 只能选择那些唯一的列
  • 很可能我们永远都不会用到不是自然联结的内部联结

外部联结

  • 联结包含了那些在相关表中没有关联行的行,这称为外部联结
SELECT Customers.cust_id, Orders.order_num 
FROM Customers LEFT OUTER JOIN Orders 
    ON Customers.cust_id = Orders.cust_id;
  • 使用关键字OUTER JOIN来指定联结的类型
  • 在使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字指定包括其所有行的表(LEFT指出的是OUTER JOIN左边的表

简化的外部联结语法

SELECT Customers.cust_id, Orders.order_num 
FROM Customers, Orders 
WHERE Customers.cust_id *= Orders.cust_id;
  • *=为左外部联结操作符,它从左边表中检索所有行
  • =*为右外部联结操作符,它从右边表中检索所有行

全外部联结

SELECT Customers.cust_id, Orders.order_num 
FROM Customers FULL OUTER JOIN Orders 
    ON Customers.cust_id = Orders.cust_id;

使用带聚集函数的联结

SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord 
FROM Customers INNER JOIN Orders 
    ON Customers.cust_id = Orders.cust_id 
GROUP BY Customers.cust_id;

使用联结和联结条件

  • 注意所使用的联结类型,一般使用内部联结
  • 注意相应的DBMS支持何种语法
  • 应该总是提供联结条件,否则会得出笛卡尔积

第14章 组合查询

  • UNION操作符,将多条SELECT语句组合成一个结果集

组合查询

  • 执行多条SELECT语句,并将结果作为单个查询结果集返回
  • 这些组合查询通常称为(union)或复合查询(compound query)
  • 有两种基本情况需要使用组合查询:
    • 在单个查询中从不同的表类似返回结构数据
    • 对单个表执行多个查询,按单个查询返回数据

创建组合查询

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';

UNION规则

  • UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔
  • UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过各个列不需要以相同的次序列出)
  • 列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含的转换的类型(例如,不同的数值类型或不同的日期类型)

包含或取消重复的行

  • UNION从查询结果集中自动去除了重复的行
  • 如果要包含重复的行,可使用UNION ALL(重复的结果)

对组合查询结果排序

  • 只能使用一条ORDER BY子句,位于最后一条SELECT语句之后
  • 会排序所有返回的结果

第15章 插入数据

  • INSERT语句
    • 插入完整的行
    • 插入行的一部分
    • 插入某些查询的结果

插入完整的行

INSERT INTO Customers
VALUES('1000000006',
    'Toy Land',
    '123 Any Street',
    'New York',
    'NY',
    '11111',
    'USA',
    NULL,
    NULL);
  • 虽然这种语法简单,但并不安全,应该尽量避免使用
  • 编写依赖于特定列次序的SQL语句是很不安全的
INSERT INTO Customers(cust_id, 
    cust_name, 
    cust_address, 
    cust_city, 
    cust_state, 
    cust_zip, 
    cust_country, 
    cust_contact, 
    cust_email)
VALUES('1000000006',
    'Toy Land',
    '123 Any Street',
    'New York',
    'NY',
    '11111',
    'USA',
    NULL,
    NULL);
  • 这样就不担心会跟表中实际列的顺序不一致了

插入部分行

  • 省略一些没有值的列
INSERT INTO Customers(cust_id, 
    cust_name, 
    cust_address, 
    cust_city, 
    cust_state, 
    cust_zip, 
    cust_country, 
VALUES('1000000006',
    'Toy Land',
    '123 Any Street',
    'New York',
    'NY',
    '11111',
    'USA',

插入检索出的数据

  • INSERT SELECT
  • 将一条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;

从一个表复制到另一个表

  • SELECT INTO
  • 将复制数据到一个新表
SELECT *
INTO CustCopy
FROM Customers;
  • 任何SELECT选项和子句都可以使用,包括WHERE和GROUP BY
  • 可利用联结从多个表插入数据
  • 不管从多少个表中检索数据,数据都只能插入到单个表中

猜你喜欢

转载自blog.csdn.net/churximi/article/details/51586861