SQL 必知必会

SQL 必知必会

第1章 了解SQL

定义

  • 结构化查询语言(Structured Query Language)

主键

  • 定义
    • 一行或一组列,其值能够唯一标识表中每一行
  • 要求
    • 任意两行不能有相同的主键值
    • 每一行都必须有一个主键值
    • 主键列中的值不能更改或更新
    • 主键值不能重用(一旦删除,不能够再赋予给以后的新行)

第2章 检索数据:SELECT

基本语法

  • SELECT Col1,Col2, FROM table

选择全部列

  • 星号 *

选择不同行

  • DISTINCT
    • 作用于所有行,不仅仅是跟在其后的一行:即只要两行不是所有列完全相同,则会被检索出来。

限制查询结果行数

  • SQL SERVER: TOP 5
    • SELECT TOP 5 student_name FROM Students
  • MYSQL :LIMIT 5 OFFESET 3
    • SELECT prod_name FROM Products LIMIT 5 OFFSET 5
    • 可以简写为LIMIT 3,5
    • 索引序号从0开始

第3章 排序检索数据:ORDER BY

语句位置

  • SELECT 语句的最后一条

指定排序列的方式

  • 按列位置(序号)排序
    • '位置'指的是SELECT语句后的列排序顺序,而不是原表中的顺序
    • 序号从1开始
    • 缺点
      • 对SELECT 清单修改时,如果没有同时修改ORDER BY的序号,容易出错。
  • 指定准确列名
    • SELECT .....
      ORDER BY col1,col2

指定顺序

  • DESC/ASC
    • 位置
      • 对应列名后
    • 默认为ASC,可省略

第4章 过滤数据:WHERE

基本操作符

  • 不等于:<>/!=
    • MSSQL和MYSQL两者都可使用
    • 可以用于字符串匹配检查
  • 不大于,不小于:!>, !<
  • BETWEEN
    • 支持字符串,日期/时间,数值的比较
  • NULL值的比较检测
    • IS NULL/IS NOT NULL
      • 专门用于NULL值得匹配
    • <=>
      • 当且仅当两个值都为NULL时才返回NULL
    • 不能使用=/<>来对NULL值进行比较或检验
    • MYSQL的NULL值处理(RUNOOB)

第5章 高级数据过滤

AND

OR

  • 注意:AND优先级高于OR。多使用括号确立优先级,即使知晓优先级。

IN

  • 语法
    • col in (a,b,c) 等价于col1 =a or col1 = b or col =c
  • 优点
    • 比对应的OR语句更快
    • 更直观
    • 配合其他select查询进行嵌套

NOT

  • 作用
    • 否认其后的条件
  • 位置
    • 位于其他判断关键词前:NOT IN

第6章 通配符:LIKE

%

  • 作用
    • 任意字符出现任意次数
      • 任意字数:可以匹配0个字符
      • 一个使用场景:字段后填补的空格的解决
        • 在匹配字符串后再加一个%,来匹配空格
  • 语法
    • SELECT *
      FROM Customers
      WHERE cust_name LIKE 'F%'
  • 不匹配NULL
    • '%'不会匹配为NULL的行
  • ACCESS 使用的是*

下划线_

  • 作用
    • 仅匹配单个字符,且不可匹配0个字符

字符集匹配

  • [ ]
    • 作用
      • 匹配字符集
    • 使用
      • SQL SERVER
        • SELECT *
          FROM Customers
          WHERE cust_name LIKE '[FV]%';
    • 语法
      • SELECT *
        FROM Customers
        WHERE cust_name RLIKE '[1]';
  • 正则表达式RLIKE(FOR MYSQL)
    • MYSQL不支持使用[]匹配字符集
    • MySQL 中使用 REGEXP 或 NOT REGEXP (或 RLIKE 和 NOT RLIKE) 和正则表达式来实现字符串匹配。
    • 语法
      • SELECT *
        FROM course
        WHERE Tno REGEXP '[2].*'
    • RUNOOB链接

^

  • 作用
    • 对[ ]进行否定:即不在方扩内的字母才能够匹配
  • 使用
    • [^JMK]

注意点

  • 使用技巧
    • ① 不要过度使用通配符
    • ② 尽量不要在搜索模式的开始使用通配符
    • ③ 特别注意通配符位置的正确使用
    • ④默认不区分大小写

第7章 创建计算字段

位置

  • 紧贴在SELECT后

别名(ALIAS)

  • 作用
    • 一个字段或值的替换名
    • 为拼接等字符操作创建的字段提供名称
  • 使用
    • AS
      • MYSQL,MSSQL都可以省略 AS

拼接字段(concatenate)

  • SQL SERVER
    • +(使用与Python相似)
  • Oracle,SQLite等
    • ||
  • MySQL,MariaDB
    • Concat()语句
      • SELECT CONCAT(id, name, work_date)
        FROM employee_tbl;

算术计算

  • +-*/
  • ()改变计算顺序

第8章 使用函数处理数据

DBMS差异:函数在各DBMS的通用度较低,只有少数函数通用。

  • 可移植
    • 代码可在不同系统上运行
    • 众多程序员建议只使用可移植的函数
  • 建议
    • 使用函数时,尽量进行注释,以帮助其他DBMS系统的使用者理解。

使用函数

  • 字符处理
    • TRIM/RTRIM/LTRIM
      • 去除空格
    • UPPER/LOWER
      • 转化为大/小写
    • LEFT/RIGHT
      • 返回字符左/右指定长度的字符
      • 使用
        • LEFT('ZENG'',2)
          返回: ‘ZE'
    • SOUNDEX
      • 匹配发音类似的项
      • 使用
        • SOUNDEX(colname) = SOUNDEX('charact')
  • 日期和时间处理
    • 可移植性最差
    • ONENOTE有网页裁剪
  • 数值处理函数
    • ABS
      • 绝对值
    • EXP
      • 自然底数的指数函数
    • SQRT
      • 平方根
    • PI
      • 圆周率
    • COS/SIN/TAN
      • 三角函数
    • MYSQL数值函数(RUNOOB)

第9章 汇总数据

汇集数据

  • COUNT
    • 计行数
      • count(*)
        • 返回总行数
      • count(col_name)
        • 返回col_name中非空行数
  • MAX
  • MIN
  • AVG
  • SUM
  • MIN,MAX,AVG,SUM的括号内都能进行列之间的数值计算

聚集函数内部的可用参数

  • DISTINCT
    • 作用
      • 聚集不同的值
    • 用法
      • AGG_FUNC(DISTINCT col_name)
  • TOP/TOP PERCENT
    • 仅支持sqlserver

组合聚集函数

  • 一个SELECT语句可以包含多个聚集函数
  • 举例
    • SELECT COUNT(*) AS num_itesm,
      MIN(prod_price) AS min_price

第10章 分组数据

创建分组:GROUP BY

  • 位置
    • WHERE后,ORDER前
  • 注意点
    • ONLY_FULL_GROUP_BY参数
      • 参数为打开状态时
        • 除聚集语句(COUNT,SUM,MAX等),所有SELECT中出现的列名,都必须在GROUP BY中出现。

过滤分组:HAVING

  • 与WHERE的关系
    • 基本语法与WHERE一致,但位置位于GROUP BY后
    • WHERE 过滤行,而HAVING过滤组
  • 使用
    • 一定是配合GROUP BY使用,一定是对分组进行过滤
    • 可以与WHERE共同使用(两者对行和分组进行过滤,不互斥)
    • 举例
      • SELECT col1,FUC(col2)
        FROM table1
        WHERE col3>0
        GROUP BY col1
        HAVING FUNC(col2) >0
      • SELECT order_num,SUM(quantity*item_price) as total_price
        FROM OrderItems
        GROUP BY order_num
        HAVING total_price>1000

第11章 使用子查询

定义

  • 嵌套在其他查询中的查询

作用

  • 利用子查询进行过滤
    • 使用
      • SELECT col1
        FROM table1
        WHERE col2 = (SELECT col2
        FROM table2
        WHERE con1)
    • 注意
      • 子查询的SELECT只能用来返回单列,不能返回多个列
  • 将子查询做为一个字段
    • 使用
      • SELECT cust_name,
        cust_state,
        (SELECT COUNT(*)
        FROM Orders
        WHERE Orders.cust_id=Customers.cust_id) AS orders
        FROM Customers
        ORDER BY cust_name
    • 注意
      • WHERE条件处要使用完全限定名
      • 等价联结语句

第12章 连接表

联结表

  • 内联结
    • 使用
      • 内联结(inner join)
        • SELECT vend_name,prod_name,prod_price
          FROM Vendors INNER JOIN Products
          ON Vendors.prod_id = Products.prod_id
          • 解释
            • SELECT 的列后的各列名,来自两个以上的不同表
              FROM 各名来自的表名
              WHERE语句指示匹配列(注意使用带表名的完全限定名)
              • 缺少WHERE/ON的联结条件语句,将返回m*n行的笛卡尔积表。m,n为两表各自的行数。
      • 等值语句
        • SELECT vend_name,prod_name,prod_price
          FROM Vendors,Products
          WHERE Vendors.prod_id = Products.prod_id
      • 联结多个表
        • 可以通过多个联结连接多个表
    • 可用于替代子查询
      • 子查询
        • SELECT cust_name,cust_contact
          FROM Customers
          WHERE Customers.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_contact
          FROM Customers
          WHERE Customers.cust_id in(
          SELECT cust_id
          FROM Orders
          WHERE order_num in(
          SELECT order_num
          FROM OrderItems
          WHERE prod_id='RGAN01'
          )
          )
    • 使用建议及注意
      • 根据SELECT 需求的列选择最少的表格及联结
      • 表格尽量少,使用的联结尽量少。 以节省运算力
      • 需满足引用完整性

第13章 高级联结

表别名

  • 在FROM语句中定义
  • SQL SERVER中,FROM语句最先运行,因此表别名可在SELECT语句中的任意阶段被使用。
  • 作用
    • 缩短SQL语句
    • 可以在一条语句中使用同一表多次,且避免歧义

使用不同类型的联结

  • 自联结
    • 需要自己控制返回的列,来避免列重复
    • 使用场景
      • 替代需要自身子查询的场景
        • SELECT *
          FROM OrderItems oi1,OrderItems oi2
          WHERE oi1.order_item=oi2.order_item AND
          oi2.prod_id='BR01'
  • 自然联结
    • SELECT *
      FROM Customers NATURAL JOIN Orders
  • 自然连接和内联结的关系和区别
    • 自然联结是特殊的内联结,自然连接自动寻找相同的列名作为匹配项
    • 内连接自己指定联结列(ON/WHERE指定),SELECT 后为*。
    • 两者返回的列数相同。
    • 但自然联结不包含两表用作匹配的列不相同的行,而inner join包含不同的列。
    • INNER JOIN 配合USING(col list) 可以达到与natural join 相同的结果
    • 小总结:NATURAL JOIN=SELECT * FROM TABLE1,TABLE2 WHERE table1.同名columns=table2.同名columns
    • 详见diigo标注部分
  • 外联结
    • 与内联结区别
      • 包含了那些在相关表中没有关联的行
    • 使用
      • LEFT OUTER JOIN
      • RIGHT OUTER JOIN
      • FULL OUTER JOIN
        • MSSQL 支持
        • MYSQL,ACCESS,SQLite等不支持

第14章 组合查询

UNION

  • 作用
    • 组合多个查询结果
    • 每个组合查询都有等效的单个使用复WHERE的语句
  • 使用
    • SELECT col1,col2,FUNC(col3)
      ...
      UNION
      SELECT col1,col2,FUNC(col3)
  • 使用注意点
    • ①包含两个及两个以上的SELECT语句
    • ②每个查询都具有相同的列名或别名,表达式或聚集函数(不要求顺序一致)
    • ③列类型必须可兼容(不一定相同,但需要可相互转换)
    • ④查询多个表时,若表名不匹配可以使用别名,别名一致即可,不要求原列名一致。
    • ⑤使用ORDER BY,只需在最后一个SELECT语句中指定排序方式即可作用在整个查询结果上

UNION ALL

  • UNION ALL保留各个SELECT语句中相同的行(UNION和等效的WHRER语句都默认去除)

EXCEPT/MINUS

  • 检索只在第一个SELECT检索的表中存在而不在第二个SELECT查询结果中的行
  • 举例
    • SELECT cust_id,cust_name,cust_contact
      FROM Customers
      WHERE cust_name='FUn4All'
      EXCEPT
      SELECT cust_id,cust_name,cust_contact
      FROM Customers
      WHERE cust_contact='Jim Jones'
  • 注意
    • ①仅部分DBMS支持
    • ②MSSQL使用EXCEPT

INTERCEPT

  • 检索在两个表格中都存在的行(交集∩)
  • 注意
    • ①部分DBMS支持
    • ②MSSQL支持
    • ③可以使用FULL OUTER JOIN 代替

第15章 插入数据

INSERT

  • 插入完整的行
    • 实例
      • INSERT INTO table1(col1_name,col2_name,..,coln_name)
        VALUES(col1_value,col2_value,...,coln_value);
        • 注意
          • 两个tuple的顺序互相一致即可,不需要与原表的列顺序一致
          • table1后的表名tuple可以省略。但不建议,因为省略该tuple后VALUES的列tuple顺序必须与table1的实际列顺序一致。
  • 插入部分行
    • 允许条件
      • 被省略的列允许NULL或者设置了默认值
    • 实例
      • 与插入完整行相似,只是两个tuple可以不完整。
      • INSERT INTO后的tuple不可省略
  • 注意
    • 一个INSERT INTO 语句只能插入一行内容

INSERT INTO ...SELECT

  • 实例
    • INSERT INTO table1(col1_name,col2_name,..,coln_name)
      SELECT col1_value,col2_value,...,coln_value
      FROM table2
      WHERE...
      • 注意
        • SELECT语句后的列名序列不需要使用括号
        • 两个列名序列的名称不要求一致
        • 两个列名序列的位置必须正确
  • 注意
    • INSERT INTO...SELECT是特殊的INSERT INTO 语句。可以根据SELECT返回结果的行数插入数据。即可以一次性插入多行。

SELECT INTO

  • 作用
    • 将SELECT选出的表插入一个新创立的table1中
  • 实例
    • SELECT col_name_tuple
      INTO table1
      FROM table2,table3
      WHERE...
      GROUP BY...
      ORDER BY...
      • 注意
        • 所有SELECT语句中可用的子语句和方法都可以用
        • table1是在该语句中新创立的表
  • 使用场景
    • 测试新的SQL语句前,创立一个新的表格用做测试
  • MYSQL不支持SELECT INTO
    • MYSQL 如何创建一个表的复制?:
      • show create table orders + insert into ... SELECT

第16课 更新和删除数据

更新数据

  • UPDATE SET
    • 实例
      • UPDATE table1
        SET col_name1 = col_value1,
        col_name2 = col_value2
        WHERE cons
  • UPDATE SELECT
    • 基本格式
      • UPDATE A a INNER JOIN B b ON b.key_id = a.key_id
        SET a.val = 2
        WHERE b.satisfy = 1
    • LEFT JOIN/RIGHT JOIN 配合GOURP BY 来修改表格
      • UPDATE course c
        RIGHT JOIN (
        SELECT Cno,AVG(score) avg_score
        FROM sc
        GROUP BY Cno
        HAVING avg_score>=75
        ) sc
        ON c.Cno=sc.Cno
        SET c.Tno="厉害老师";

SELECT *
FROM course;

  • UPDATE FROM

删除数据

  • 删除某表中的部分数据
    • DELETE FROM
      • DELETE FROM table
        WHERE cons
  • 删除全部数据
    • DELETE FROM table1
    • TRUNCATE table1
      • 比DELETE更快

使用更新和删除注意点

  • 建议UPDATE或删除前使用SELECT进行测试,保证进行正确的操作(对WHERE语句)
  • 务必考虑并实施引用完整性的数据库
  • 部分DBMS有强制使用WHERE的选项,尽量使用

第17章 创建和操纵表

创建表

  • 实例
    • CREATE TABLE table_name
      (col1_name char(10) NOT NULL,
      col2_name DECIMAL(8,2) NULL,
      ...
      coln_name (data_type) (NULL/NOT NULL)
      )
  • 注意点
    • 大部分DBMS NULL/NOT NULL一项默认NULL,因此NULL可省略
    • 设定默认值:对应列的NULL/NOT NULL后添加DEFAULT default_value(常使用日期函数做为默认值)
      • 日期函数
        • MSSQL
          • GETDATE()
        • MYSQL
          • CURRENT_DATE()
    • 注意一个字段的名称,类型,是否为空之间是不需要空格的。
  • 建议
    • 尽量给定DEFAULT值,而定义为NULL

更新表

  • 注意点
    • 尽量在创立表时,就考虑好未来需求,减少表的修改。
    • 大多数表支持新增列或者更改无内容填充的列的操作
    • 大多数表不支持 删除或更改表中的列,重新命名表中的列,对已有内容填充的表的修改
  • 示例
    • 新增列
      • ALTER TABLE table1
        ADD col_name data_type NULL/NOTNULL
      • 大多数DBMS支持
    • 删除列
      • ALTER TABLE table1
        DROP col_name
      • DBMS 支持通用度不高
    • 修改表
      • ALTER CHANGE
      • ALTER MODIFY
    • 修改表名
      • ALTER TABLE testalter_tbl RENAME TO alter_tbl;
    • 复杂表更改的一般流程
      • 按照新需求创建一个新的表格
      • 复制原表仍需要的数据内容到新表(UPDATE SELECT)
      • 检查插入数据后的新表
      • 更改原表表名或直接删除
      • 将新表更改为原表表名
      • 根据需要,重新建立触发器,储存过程,索引和外键
    • 注意点
      • ALTER的使用需尽量小心,更改前做好备份
    • RUNNOOB关于ALTER TABLE

删除表

  • DROP table1
    • 遵循引用完整性的等关系规则
  • MYSQL
    • DROP TABLE table_name

重命名表格

  • sp_rename 储存过程
    • MSSQL
  • RENAME
    • MSSQL,SQLite外的大多数DBMS

第18课 使用视图

视图作用

  • 重用SQL语句,简化操作
  • 权限管理,只允许查看视图内容,而非整个表
  • 展示与原表不同的数据格式和内容

注意

  • 每次使用视图,都会重新运行一次查询。因此复杂视图会影响性能

限制规则

  • 命名唯一
  • 可进行权限管理
  • 可以嵌套(但嵌套会提高复杂度,占用更多运算力)
  • 众多DBMS进制在视图的定义时的查询语句中使用ORDER BY
    • SQL SERVER不允许。但是如果SELECT语句后添加TOP 关键字,则可以使用。
  • 部分DBMS将视图设置为只读,即不可更新视图内容并写入底层原表
  • 部分DBMS允许创建一种视图,视图限制原表内容修改会导致视图行数减少的操作
  • 参照具体的DBMS

创建视图

  • CREATE VIEW view_name AS
    SELECT 语句

使用建议

  • 创建不绑定特定数据的视图(如限定某个id为具体值),而在使用视图时再进行限定。

第19课 使用储存过程

定义

  • 为以后使用而保存的一条或多条SQL语句。可以视为批处理(但不只是批处理)

使用

  • 计Customers中带邮件的行数
    • 创建
      • CREATE PROCEDURE MailingListCounting
        AS
        DECLARE @cnt INTEGER
        SELECT @cnt = COUNT(*)
        FROM Customers
        WHERE NOT cust_email IS NULL
    • 使用
      • DECLARE @RETURNVALUE INT
        @RETURNVALUE = MailingListCounting
        SELECT @RETURNVALUE
  • 在ORDERS表单插入新订单
    • 创建方法①
      • CREATE PRODUCE NewOrder @cust_id CHAR(10)
        AS
        DECLARE @order_num INTEGER
        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

- 创建方法②

    - CREATE PRODUCE NewOrder @cust_id CHAR(10)

AS
INSERT INTO Orders(cust_id)
VALUES(cust_id)

SELECT cust_num = @@IDENTITY

        - 方法②的日期由创建表格时的DEFAULT GETDATE()给出

order_num由标识字段(identity field)给出

注意点

  • 使用频率远高于创建,创建与使用权限可分隔

第20课 管理事务处理

事务处理

  • 可回退的语句
    • INSERT
    • UPDATE
    • DELETE
  • 不可回退的语句
    • SELECT
    • DROP
    • CREATE

控制事务处理

  • 事务(TRANSCATION)
    • BEGIN TRANSCATION
      ...
      COMMIT TRANSCATION
    • 省略号部分,要么全部执行,如果中间某句出错,则全部不执行
  • 回滚(ROLLBACK)
    • 作用
      • 使数据库回到上次COMMIT或者TRANCATION的状态
  • 保留点(SAVE)
    • 实例
      • SAVE TRANSACTION delete1;

ROLLBACK TRANSACTION delete1:

- 注意

    - 每个回滚点的名称必须唯一(本实例为delete1)
    - 常用回滚条件:

IF @@ERROR <>0 ROLLBACK TRANSCATION delete1;

补充

ONLY_FULL_GROUP_BY

  • Mysql的WHERE 语句的联结Group by似乎不要求聚合函数外的所有列。但JOIN ON 要求有
    • SELECT c.cust_id,c.cust_name,c.cust_state,COUNT(o.order_num) nums
      FROM Customers c,Orders o
      WHERE c.cust_id=o.cust_id
      GROUP BY c.cust_id;
    • ANSWER
      • sql_mode下的ONLY_FULL_GROUP_BY默认打开

大小写区分

  • 默认大小写不区分,但可以通过设置更改为敏感

注释

  • 符号
    • 单行注释
      • -- comments
    • 多行注释
      • /* comments1
        comments2 */

数值型补零前后的值大小相同

  • 3.49,3.490大小相同,条件筛选不用区分

MSSQL语句顺序

  • 运行顺序
    • (1) FROM < left_table>

(3) < join_type> JOIN < right_table> (2) ON < join_condition>

(4) WHERE < where_condition>

(5) GROUP BY < group_by_list>

(6) WITH {cube | rollup}

(7) HAVING < having_condition>

(8) SELECT (9) DISTINCT (11) < top_specification> < select_list>

(10) ORDER BY < order_by_list>

    - FORM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1

ON: 对虚表VT1进行ON筛选,只有那些符合 的行才会被记录在虚表VT2中。
JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, rug from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。
WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合 的记录才会被插入到虚拟表VT4中。
GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5.
CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6.
HAVING: 对虚拟表VT6应用having过滤,只有符合 的记录才会被 插入到虚拟表VT7中。
SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。
DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9.
ORDER BY: 将虚拟表VT9中的记录按照<order_by_list>进行排序操作,产生虚拟表VT10.
LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。

        - 理解:FROM 中定义的别名,可以全局引用
  • 书写顺序
    • SELECT DISTINCT
      FROM
      JOIN
      ON
      WHERE
      GROUP BY
      HAVING
      ORDER
      LIMIT
  • 因此别名在SELECT创建,则只能在SELECT和ORDER BY语句中使用。

NULL不是空字符串

  • NULL是没有值,而“”可以理解为0长度的字符串

from: https://www.jianshu.com/p/765fbb31ff6f


  1. FV ↩︎

  2. 张王 ↩︎

猜你喜欢

转载自www.cnblogs.com/geoffreygao/p/13364558.html