(My)SQL

Posted Mibloom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(My)SQL相关的知识,希望对你有一定的参考价值。

1.SQL语句分类

  1. DDL(Data Definition Languages)语句:用来创建 删除 修改数据库、表、列、索引等数据库对象。常用的语句关键字主要包括create、drop、alter等。
  2. DML(Data Manipulation Language)语句:数据操纵语句,对数据库表中的数据进行添加、删除、更新和查询,并检查数据完整性。常用的语句关键字主要包括insert、delete、update和select等。
  3. DCL(Data Control Language)语句:数据控制语句,用于控制不同数据段直接的许可和访问级别的语句。这些语句定义了数据库、表、字段、用户的访问权限和安全级别。主要的语句关键字包括grant、revoke等。

2.DDL语句

  1. 和数据库相关

    1. 创建数据库 CREATE DATABASE  db_name;   (SQL语句可以 ; 作为结束标志也可以使用 \\g 作为结束标志。)
    2. 删除数据库 DROP DATABASE db_name;
    3. 使用数据库 USE db_name;
    4. 显示所有数据库 SHOW DATABASES; 
    5. 显示当前数据库所有表 SHOW TABLES;
  2. 和表相关

    1. 创建表: CREATE TABLE t_name( col_name col_TYPE . . .);
    2. 删除表:DROP TABLE t_name;
    3. 查询表定义: DESC t_name; 
    4. 查询表定义的SQL语句:SHOW CREATE TABLE t_naem;
    5. AS : 为表或者字段添加别名, 不使用as 直接在表名或者字段名后面一个空格 和 别名也是可以的。
    6. 修改表:ALTER 

      • 中括号表示其中的元素可有可无。
      • 可以指定修改后的位置,FIRST 表示第一列, AFTER col_name 表示在某列之后。
      1. MODIFY 修改表字段类型
        • 如varchar(10)改为varchar(20) : ALTER TABLE t_name MODIFY  [COLUMN] col_naem  varchar(20)  [FIRST|AFTER col_name]
        • 默认位置不变。
      2. ADD 添加表字段
        • ALTER TABLE t_name ADD [COLUMN]con_name int(3) [FIRST|AFTER col_name]
        • 默认添加在最后。
      3. DROP删除字段
        • ALTER TABLE t_name DROP [COLUMN] col_name;
      4. CHANGE 可以用来修改字段名称
        • ALTER TABLE t_name CHANGE [COLUMN] old_col_name  new_col_naem TYPE [FIRST|AFTER col_name];
        • 默认位置不变。
      5. RENAME 修改表名
        • ALTER TABLE t_name RENAME [TO] new_t_name;
      • MODIFY 与 CHANGE 都可以修改字段类型(CHANGE 需要写2遍列名,不方便),但是 CHANGE优点就是可以修改字段名称。
      • CHANGE/FIRST|AFTER COLUMN这些关键字都属于mysql在标准SQL上的扩展,在其他数据库上不一定适用。

3.DML语句

  1. INSERT 插入数据
    1. INSERT INTO tablename (field1,field2,…,fieldn) VALUES(value1,value2,…,valuen); 
    2. 自增,设有默认值,可以为NULL的字段,可以不出现在 字段列表中,但要始终保持字段列表和值列表一一对应。
    3. 也可以不用指定字段名称,但是values后面的顺序应该和字段的排列顺序一致,如果有自增字段值应该对应写 \'\'(空字符)。
      --如插入数据  id(自增),年龄,性别
      INSERT INTO t_name values(\'\', 20, \'man\')
    4. INSERT 可以一次性插入多条数据,插入值之间用“ , ”分割。 这个特性可以使得MySQL在插入大量数据时节省很多的网络开销,大大提高插入效率。
      INSERT INTO emp(name,age) VALUES(\'孙悟空\',100),(\'猪八戒\',100),(\'唐三藏\',100)
    5. INSERT INTO t1_name SELECT .... FROM t2_naem ....
      1. 要求t1表必须存在。
      2. 从t2表中查找出数据插入t1表中,值类型需要相符,但是如果值是数字或者null那么int 和 varchar 可以互。
      3. 也可以简单赋值,如emp只有一个字段int 或者 varchar :INSERT INTO emp select  20;
    6. 还有一种插入数据方法 SELECT * into t2 from t1; 这要求T2不存在并且会创建t2表,但是MySQL不支持这种写法
  2. UPDATE 更新数据 
    1. UPDATE t_name SET  field1 = valve1, field2 = value2 [WHERE 条件];
    2. 没有 where条件 就会把所有值设为相同值。
    3. 一次更新多个表中的记录
      update emp a,dept b
      set 
      a.sal=a.sal*b.deptno,
      b.deptname=a.ename 
      wherea.deptno=b.deptno;

       注意别名的用法:设置别名就是为了便捷,所以选择表时如果设置了别名之后使用时就用别名,如果不用别名有时会出现SQL语句错误。

  3. DELETE 删除记录
    1. 删除单个表中某行记录 :DELETE FROM t_naem  [WHERE 条件];
    2. 删除多个表中的记录:如果FROM 后面表加了别名那么FROM必须要用表的别名。
      DELETE t1,tt,t3 FROM,t2 tt ,t3  [WHERE 条件]
    3. 没有where条件会将整个表清空,所以where条件很重要。
  4. SELECT 查询记录
    1. 最基本语法 SELECT * FROM t_name [WHERE 条件];

4.查询数据

  • 对于查询处理,可将其分为逻辑查询处理及物理查询处理。逻辑查询处理表示执行查询应该产生什么样的结果,而物理查询代表MySQL数据库是如何得到该结果的。两种查询的方法可能完全不同,但是得到的结果必定是相同的。
  • 在SQL语言逻辑查询中,第一个被处理的子句总是FROM子句,查询顺序如下图
  • (摘自 《MySQL技术内幕:SQL编程》)
  1. FROM 做笛卡尔积

    1. 如果有 JOIN 则首先对FROM子句中的左表<left_table>和右表<right_table>做笛卡儿积,产生虚拟表VT1。再执行 2。
    2. 如果没有 JOIN 即不做表连接,则对FROM后面的表做笛卡尔积。执行4。
  2. ON 对JOIN后的结果过滤

    • JOIN 分为 内连接 [INNER] JOIN 和 外连接  [OUTER] JOIN
    • 外连接 又分为:LEFT [OUTER] JOIN  和  RIGHT [OUTER] JOIN
    1. 只有JOIN 左右最近的一个表才是左表右表生成VT1,这两个表会执行ON条件,所以ON中只能出现这两个表的字段,其他表中的字段不在VT1中所以不能出现在ON中。
    2. 对于符合条件的行会标志认为TRUE,不符合条件的行标志位FALSE。
    3. 对于等号一边的一个条件对应值NULL,则标记为FALSE,如果2个条件都为NULL,则标记为UNKNOWN, UNKNOWN也被当做FALSE处理。
    4. ON对2个NULL的处理和 ORDER BY 、GROUP BY不同,ORDER BY 会把所有NULL值分到同一组,GROUP BY会认为他们是不同的排列在一起。
    5. 对虚拟表VT1应用ON筛选,只有那些符合<join_condition>也就是被标注为TRUE的行才被插入虚拟表VT2中。
    6. ON 只对JOIN的表过滤,没有JOIN是不能使用ON过滤的。
    7. SELECT查询一共有3个过滤过程,分别是ON、WHERE、HAVING。ON是最先执行的过滤过程。
  3. OUTER JOIN 以某一张表为基表保留 进行相关查询

    • 只有外连接才会执行这一步
    1. 如果指定了OUTER JOIN(如LEFT [OUTER] JOIN、RIGHT [OUTER] JOIN),那么保留表中未匹配的行作为外部行添加到虚拟表VT2中,产生虚拟表VT3。
    2. 如果需要连接表的数量大于2,则对上一个连接生成的结果表VT3和下一个表重复执行步骤1)~步骤3),直到处理完所有的表为止。
      SELECT * 
      FROM  customers AS c
      LEFT JOIN orders AS o
      ON c.customer_id = o.customer_id
      RIGHT JOIN emp
      ON emp.age=20;
  4. WHERE 条件查询

    1. where后面的条件可以使用=,除了=外,还可以使用>、<、>=、<=、!=等比较运算符;
    2. 多个条件之间还可以使用or、and等逻辑运算符进行多条件联合查询。
    3. 外连接下ON会保留基表被过滤的行,而WHERE则不会保留,内连接ON 和WHERE作用一样。
    4. 由于数据还没有分组,因此现在还不能在WHERE过滤器中使用 统计类函数。 
    5. 因为WHERE 在SELECT 之前执行,所以在SELECT 中设定的字段别名在WHERE中时不能使用的,同样的道理FROM 最先执行所以FROM设定的表的别名在任何地方都能使用。
      SELECT NAME,age 年龄
      FROM  emp  e
      WHERE e.age=20;
  5. GROUP BY

    1. 分组的目的就是为了使用 统计类函数。
    2. GROUP BY 还有一个作用就是去重,它只会返回一组的一个值。
    3. 根据GROUP BY子句中的列,对VT4中的记录进行分组操作,产生VT5。
    4. 根据要分组的列判断是否为同一组。 单列就比较此列,多列就要多列都相同才认为同一组。
    5. GROUP BY默认会根据该字段排序,相当于执行了一次ORDER BY...ASC 。
  6. CUBE|ROLLUP

    1. 对表VT5进行CUBE或ROLLUP操作,产生表VT6,使用CULB和ROLLUP要加上WITH 。
    2. MySQL数据库虽然支持该关键字CUBE的解析,但是并未实现该功能。
    3. 如果指定了ROLLUP选项,那么将创建一个额外的记录添加到虚拟表VT5的最后,并生成虚拟表VT6。
    4. ROLLUP是根据维度在数据结果集中进行的聚合操作,他和GROUP BY 的列息息相关。
    5. 聚合操作就是对某一项所有不同数据进行统计,而维度就是要聚合的数量。
    6. WITH ROLLUP,在分组的统计数据的基础上再进行相同的统计(SUM,AVG,COUNT…),而其他字段为null,可以根据这个特定判断是对象还是统计结果。
    7. SELECT  empid,custid,  YEAR(orderdate) YEAR,  SUM(qty) SUM
      FROM t
      GROUP BY empid,custid,YEAR(orderdate)
      WITH ROLLUP;

    8. 如果分组的列包含NULL值,那么ROLLUP的结果可能是不正确的,因为在ROLLUP中进行分组统计时值NULL具有特殊意义。因此在进行ROLLUP操作时,可以先将NULL值转换为一个不可能存在的值,或者没有特别含义的值,例如:IFNULL(XXX, 0)    IFNULL函数是MySQL控制流函数之一,它接受两个参数,如果不是NULL,则返回第一个参数。 否则,IFNULL函数返回第二个参数。
  7. HAVING

    1. 对虚拟表VT6应用HAVING过滤器,只有符合<having_condition>的记录才被插入虚拟表VT7中
    2. 分组后对分组进行过滤,过滤条件一般是判断聚合函数的值
    3. 需要特别注意的是,过滤函数中不能使用COUNT(1)或COUNT(*),因为这会把通过OUTER JOIN添加的行统计入内而导致最终查询结果与预期结果不同。
    4. COUNT(id) 要使用具体的列。
  8. SELECT

    1. 选择指定的列,插入到虚拟表VT8中。
  9. DISTINCT查询不重复的记录

    1. SELECT DISTINCT name FROM t_name;  它会返回所有不同的name
    2. SELECT DISTINCT id,name FROM t_name;  只有2条记录的id和name都相同才会被去除。
    3. SELECT id,DISTINCT  name FROM t_name; 这样是非法的,DISTINCT只能用在所有字段的最前面。
    4. 所以DISTINCT无法做到 只对某一字段去重 同时显示其他内容。
    5. DISTINCT一般用来记录 不重复的记录数量SELECT  COUNT(DISTINCT naem) FROM t_name;
    6. GROUP BY 之后使用DISTINCT 无意义,因为GROUP BY也会去重。
  10. ORDER BY排序

    1. 用来对查询结果排序
      SELECT*FROM tablename [WHERE CONDITION] [ORDER BYfield1 [DESC|ASC],field2 [DESC|ASC],…,fieldn [DESC|ASC]]
    2. ASC 代表升序,第一行最小,最后一行最大,DESC 代表降序,第一行最大,最后一行最小。默认升序。
    3. 可以对多个字段排序,且可以使用不同的排序规则,如果第一个字段有相同的则会根据第二个字段排序。
    4. 不要为表中的行假定任何特定的顺序。就是说,在实际使用环境中,如果确实需要有序输出行记录,则必须使用ORDER BY子句
    5. 因为没有ORDER BY子句的查询只代表从集合中查询数据,而集合是没有顺序概念的。
    6. 在ORDER BY子句中,NULL值被认为是相同的值,会将其排序在一起。在MySQL数据库中,NULL值在升序过程中总是首先被选出,即NULL值在ORDER BY子句中最小的。
    7. WITH ROLLUP与ORDER BY相互排斥,不能同时使用。
    8. ORDER BY子句中指定SELECT列表中列的序列号,如下面的语句:

      SELECT order_id,customer_id
      FROM orders
      ORDER BY 2,1; -- 等同于:
      SELECT order_id,customer_id
      FROM orders
      ORDER BY customer_id,order_id;

       

  11. LIMIT限制

    1. LIMIT 是最后一个执行的条件。
    2. LIMIT start ,count : start 是起始位置, count 是数量而不是结束位置,可以不写 start 默认是0 ,如 从第3条开始选10条记录 :limit 3,10;

5.物理查询

  1. 数据库引擎不会按照逻辑查询那样去一步一步执行,它有大量优化操作,但最终结果和逻辑查询是一样的。
  2. 比如 索引的使用就避免的 笛卡尔积 的产生,大大缩短了运行时间。

6.子查询

以上是关于(My)SQL的主要内容,如果未能解决你的问题,请参考以下文章

缺少 SQL SERVER 2014 代码片段

sql Oracle代码片段

sql 日期转换代码片段 - Dato,120,konvertere

以下代码片段是不是容易受到 Rails 5 中 SQL 注入的影响?

Discuz代码片段

使用实体框架迁移时 SQL Server 连接抛出异常 - 添加代码片段