Sql:基础

旧时模样 提交于 2020-03-19 05:57:14

本文根据书籍《sql必知必会》,整理而成。

基本概念

数据库 database:保存有组织的数据的容器,通常是一个文件或一组文件。

数据库管理系统 DBMS:又称数据库软件,数据库是通过 DBMS 创建和操纵的容器。

表 table:某种特定类型数据的结构化清单。

模式 schema:关于数据库和表的布局及特性的信息。

列 column:表中的一个字段。所有的表都是由一个或多个列组成的。

行 row:表中的一个记录,有时又称为数据库记录 record。

主键 primary key:一列(或一组列),其值能够唯一标识表中每一行。

关键字 keyword:作为 SQL 组成部分的保留字。

子句 clause:SQL 语句由子句构成,有些子句是必需的,有些则是可选的。一个子句通常由一个关键字加上所提供的数据组成。例如 SELECT 语句中的 FROM 子句。 

SQL 是结构化查询语言(structured query language)的缩写。SQL 是一种专门用来与数据库沟通的语言。

检索数据

基本查询用 SELECT 语句

SELECT DISTINCT prod_id, prod_name FROM Products LIMIT 5 OFFSET 5;

注意:DISTINCT 关键字作用于所有的列。LIMIT 5 OFFSET 5 指示 MySQL 等 DBMS 返回从第 5 行起的 5 行数据。第一个数字是指从哪儿开始,第二个数字是检索的行数。

排序数据

SELECT prod_id, prod_price, prod_name FROM Products ORDER BY prod_price DESC, prod_name;

注意:ORDER BY 子句必须是 SELECT 语句中的最后一条子句。同时使用 ORDER BY 和 WHERE 时,应该让 ORDER BY 位于 WHERE 之后。

过滤数据

filter condition 提取表数据的子集。

可以通过

  • 关系运算 >=< 空值检查 IS NULL
  • 逻辑运算 AND NOT IN NOT 等

来过滤数据。

关键字 DISTINCT 关键字,指示数据库只返回不同的值。DISTINCT 关键字作用于所有的列。

搜索数据

通配符 wildcard:用来匹配值的一部分的特殊字符。

搜索模式 search pattern:由字面值、通配符或两者组合构成的搜索条件。

谓词 predicate:操作符何时不是操作符?答案是,它作为谓词时。从技术上说,LIKE 是谓词而不是操作符。虽然最终结果是相同的。

常用的通配符有百分号 % 下划线 _ 方括号 [ ] 等。

计算字段

拼接字段,concat 就是一个函数

SELECT
    Concat(
        vend_name,
        ' (',
        vend_country,
        ')'
    ) AS vend_title
FROM
    Vendors
ORDER BY
    vend_name;

 执行算术计算

SELECT
    prod_id,
    quantity,
    item_price,
    quantity * item_price AS expanded_price
FROM
    OrderItems
WHERE
    order_num = 20008;

 其他算术运算符也可以使用。

汇总数据

首先讲讲函数,函数在多种编程语言里面皆有定义,SQL 中定义和它们差不多。

函数主要分为文本处理函数、日期和时间处理函数、数值处理函数。重点是聚集函数。

聚集函数 aggregate function:对某些行运行的函数,计算并返回一个值。常用的有:

  • AVG 求平均值,例如:SELECT AVG(prod_price) AS avg_price FROM Products;
  • COUNT 计数,例如:SELECT COUNT(*) AS num_cust FROM Customers;
  • MAX MIN 最大值和最小值,例如:SELECT MAX(prod_price) AS max_price FROM Products;
  • SUM 指定列的和,例如:SELECT SUM(quantity) AS items_ordered FROM OrderItems;

上面这些函数可以组合使用。

分组数据

汇总表内容的子集。主要是 GROUP BY 子句和 HAVING 子句。

 例如:

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

GROUP BY 子句指示 DBMS 分组数据,然后对每个组而不是整个结果集进行聚集。 

关于 GROUP BY 的一些重要的规定。 

一般用 HAVEING 子句过滤分组。HAVEING 分句非常类似于 WHERE。唯一的差别是,WHERE 过滤行,而 HAVING 过滤分组。二者句法是相同的。WHERE 在数据分组前进行过滤,HAVING 在数据分组后进行过滤。

SELECT
    cust_id,
    COUNT(*) AS orders
FROM
    Orders
GROUP BY
    cust_id
HAVING
    COUNT(*) >= 2;

 GROUP BY 和 ORDER BY 的组合使用。

SELECT
    order_num,
    COUNT(*) AS items
FROM
    OrderItems
GROUP BY
    order_num
HAVING
    COUNT(*) >= 3
ORDER BY
    items,
    order_num;

注意子句的顺序。 

子查询

子查询 subquery,即嵌套在其他查询中的查询。在 SELECT 语句中,子查询总是从内向外处理。

SELECT cust_name, cust_contact
FROM Customers
WHERE cust_id IN (
    SELECT cust_id
    FROM orders
    WHERE order_num IN (
        SELECT order_num
        FROM OrderItems
        WHERE prod_id = 'RGAN01'
    )
);

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

SELECT cust_name, cust_state
    , (
        SELECT COUNT(*)
        FROM Orders
        WHERE Orders.cust_id = Customers.cust_id
    ) AS orders
FROM Customers
ORDER BY cust_name;

以上是常见的子查询。 

组合查询

在数据查询中执行联结表 join。 

笛卡儿积 cartesian product:由没有联结条件的表返回的结果为笛卡儿积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。

例如:SELECT vend_name, prod_name, prod_price FROM Vendors, Products;

这样查询的结果一般不是我们想要的。

内联结

等值联结 equijoin:又称内联结 inner join,它基于两个表之间的相等测试。

带条件的联结,这是简单语法

SELECT vend_name, prod_name, prod_price
FROM Vendors, Products
WHERE Vendors.vend_id = Products.vend_id;

 带条件的联结,这是标准语法

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

注意 inner join 可以多次使用连接多个表。 

SELECT prod_name, vend_name, prod_price, quantity
FROM Products 
INNER JOIN Vendors ON Products.vend_id = Vendors.vend_id
INNER JOIN OrderItems ON OrderItems.prod_id = Products.prod_id
WHERE order_num = 20007;

 联结多个表

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

表别名:表别名只能在查询执行中使用。与列别名不一样,表别名不返回到客户端。

自联结

self-join 

SELECT c1.cust_id, c1.cust_name, c1.cust_contact
FROM Customers c1, Customers c2
WHERE c1.cust_name = c2.cust_name
    AND c2.cust_contact = 'Jim Jones';

 许多 DBMS 处理联结远比处理子查询快得多。

自然联结

natural join

SELECT C.*, O.order_num, O.order_date, OI.prod_id, OI.quantity
    , OI.item_price
FROM Customers C, Orders O, OrderItems OI
WHERE (C.cust_id = O.cust_id
    AND OI.order_num = O.order_num
    AND prod_id = 'RGAN01');

 无论何时对表进行联结,应该至少有一列不止出现在一个表中(被联结的列)。标准的联结返回所有数据,相同的列甚至多次出现。自然联结排除多次出现,使每一列只返回一次。

外联结

outer join

这是左联结

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

 这是右联结

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

 许多联结将一个表中的行与另一个表中的行相关联,但有时候需要包含没有关联行的那些行。

利用 UNION,可以把多条查询的结果作为一条组合查询返回。

内联结是两张表中具有数据对应时才会产生一行记录。外联结则是以主表为准根据附表产生对应的记录。

插入更新删除数据

插入数据

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_contact, cust_email, cust_name, cust_address
    , cust_city, cust_state, cust_zip, cust_country)
SELECT cust_id, cust_contact, cust_email, cust_name, cust_address
    , cust_city, cust_state, cust_zip, cust_country
FROM CustNew;

上面的 INSERT SELECT 中 SELECT 语句可以包含 WHERE 子句,以过滤插入的数据。

INSERT 通常只插入一行。要插入多行,必须执行多个 INSERT 语句。INSERT SELECT 是个例外,它可以用一条 INSERT 插入多行,不管 SELECT 语句返回多少行,都将被 INSERT 插入。

从一个表复制到另一个表

CREATE TABLE CustCopy AS
SELECT * FROM Customers;

 更新数据

UPDATE customers
SET cust_email = 'kim@thetoystore.com'
WHERE cust_id = '1000000005';

 删除数据

DELETE FROM Customers
WHERE cust_id = '1000000006';

视图

视图是虚拟的表。与包含数据的表不一样,视图只包含使用时动态检索数据的查询。

因为视图不包含数据,所以每次使用视图时,都必须处理查询执行时需要的所有检索。如果你用多个联结和过滤创建了复杂的视图或者嵌套了视图,性能可能会下降得很厉害。因此,在部署使用了大量视图的应用前,应该进行测试。

创建视图

CREATE VIEW ProductCustomers
AS
SELECT cust_name, cust_contact, prod_id
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id = Orders.cust_id
    AND OrderItems.order_num = Orders.order_num;

视图的查询和普通的 SELECT 语句一样。

存储过程

存储过程就是为以后使用而保存的一条或多条 SQL 语句。可将其视为批文件,虽然它们的作用不仅限于批处理。 

事务处理

使用事务处理 transaction processing,通过确保成批的 SQL 操作要么完全操作,要么完全不执行,来维护数据库的完整性。

事务处理相关的术语:

  • 事务 transaction 指一组 SQL 语句;
  • 回退 rollback 指撤销指定 SQL 语句的过程;
  • 提交 commit 指将未存储的 SQL 语句结果写入数据库表;
  • 保留点 savepoint 指事务处理中设置的临时占位符 placeholder,可以对它发布回退(与回退整个事物处理不同)。

事务处理用来管理 INSERT UPDATE DELETE 语句。

游标

游标 cursor 是一个存储在 DBMS 服务器上的数据库查询,它不是一条 SELECT 语句,而是被该语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。

有时,需要在检索出来的行中前进或后退一行或多行,这就是游标的用途所在。

高级 SQL 特性

约束

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

主键 primary key:是一种特殊的约束,用来保证一列(或一组列)中的值是唯一的,而且永不改动。

外键是表中的一列,其值必须列在另一表的主键中。外键是保证引用完整性的极其重要的部分。

唯一约束 UNIQUE 可以用于限制某一列的值不重复。

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

  • 检查最小或最大值。例如,防止 0 个物品的订单;
  • 指定范围。例如,保证发货日期大于等于今天的日期;
  • 只允许特定的值。

索引

创建索引

CREATE INDEX prod_name_ind ON PRODUCTS (prod_name);

触发器 

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

 

综合查询:

显示所有的库:show database;

使用名为 test 的库:use test;

显示库中所有的表:show tables;

显示表的所有信息:describe pet; 

 

参考:

mysql 官方文档

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!