MySQL语法心得总结(不定期更新)

文章目录

      • 数据库基本操作
        • 连接MySQL
        • MySQL服务退出
        • 查看MySQL版本号
        • 显示数据库实例中的数据库
        • 删除数据库
        • 使用数据库
        • 显示当前使用的数据库
        • 显示数据库中所有表
        • 查看表结构
        • 查看表创建状态
        • 创建表
          • 独自创建新表
          • 复制旧表到新表
        • 删除表
        • 修改表
          • 修改表名
        • 修改字段类型或添加某些约束(`MODIFY`,`CHANGE`)
        • 添加/删除字段(`ADD`,`DROP`)
        • 插入记录
        • 删除记录
        • 更新记录
      • 小Tips
        • 着重号 `
        • +号的作用
        • 通配符 % 和 _
        • 安全等于 <=>
        • ISNULL()函数
      • 常见函数
        • 常见字符函数
        • 常见数学函数
          • 数字精度函数
          • 算术函数
        • 常见日期函数
        • 类型转换函数 CAST()
      • 分组和聚集
        • 分组
          • One Tip:WITH ROLLUP
        • 聚集函数
          • Tips
      • 连接
        • 内连接
        • 外连接
        • 交叉连接
        • 自然连接
      • 条件逻辑---流程控制语句( IF和CASE )
        • IF语句
        • CASE语句
        • 控制流函数IFNULL()
      • 事务
      • 索引
        • 创建普通索引
        • 创建唯一索引
        • 查看索引
        • 删除索引
      • 约束
        • 创建约束
        • 删除约束
      • 视图
        • 创建视图/更新视图
        • 删除视图
      • 元数据
        • information_schema
        • 使用元数据
      • 推荐书籍

数据库基本操作

连接MySQL

  • TCP/IP套接字方式

    mysql [-h 主机IP -P 端口号]
    -u 用户名 
    -p密码 
    [数据库名] -e 'sql语句';
    //最后加上数据库名可直接选中数据库
    
  • Unix域套接字
    该方式只适用于mysql客户端和数据库实例在同一台服务器上的情况.
    先找出Unix域套接字文件位置

    SHOW VARIABLES LIKE 'socket';
    -> /tmp/mysql.sock //在该位置
    

    接着就可以用它连接了

    mysql -S /tmp/mysql.sock -u 用户名 -p 密码
    

MySQL服务退出

EXIT;

查看MySQL版本号

SELECT version();

显示数据库实例中的数据库

SHOW databases;

删除数据库

DROP database 数据库名;

使用数据库

USE 数据库名;

显示当前使用的数据库

SELECT database();

显示数据库中所有表

SHOW tables;   
OR  
SHOW tables from 数据库名; 

查看表结构

DESC 表名;//基本表结构
or
SHOW CREATE TABLE 表名;//详细表结构

查看表创建状态

SHOW TABLE STATUS LIKE '表名';

创建表

独自创建新表
CREATE TABLE 表名(  
列名 列类型 not null primary key,  
列名 列类型 auto_increment,
列名 列类型 default(value), 
constraint 约束名 foreign key(列名) references 另一个表名(列名) 
. . .   
);
复制旧表到新表
方式1:
CREATE TABLE 新表名
AS
SELECT * FROM 旧表名;

方式2:
SELECT *
INTO 新表名
FROM 旧表名
[WHERE condition]; //添加过滤条件可插入部分记录.  

方式3:
INSERT INTO 新表名
SELECT * FROM 旧表名;

删除表

DROP TABLE 表名;

⚠️若要删除的表中有外键约束,需要先删除外键约束,再用上述命令删除表.

修改表

修改表名
ALTER TABLE 旧表名 RENAME TO 新表名;

修改字段类型或添加某些约束(MODIFY,CHANGE)

ALTER TABLE 表名 MODIFY 字段名 要修改的字段类型 
[添加一些约束,如not null, unique, default xxx]
or 修改字段名如下
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 新字段类型;

添加/删除字段(ADD,DROP)

ALTER TABLE 表名 ADD 字段名 字段类型;
or
ALTER TABLE 表名 DROP 字段名;

插入记录

INSERT INTO 表名(C1,C2,...,Cn)
VALUES(....,
      ....,
      .....);

删除记录

DELETE FROM 表名
WHERE 过滤条件;
//不加过滤条件则删除整张表记录

更新记录

UPDATE 表名
SET1=1,2=2,...
WHERE 过滤条件;

小Tips

着重号 `

用以区分关键字和字段名,如
SELECT NAME FROM xxx
中NAME为关键字,易引起歧义,故可加上着重号表示它为字段名而非关键字,即

SELECT `NAME` FROM xxx 

+号的作用

在mysql中,+号只表示为运算符.
CASE1: SELECT 10+90;      结果为100.
CASE2: SELECT ‘10’+90;      结果也为100,即若其中一方为字符型,mysql试图会将其转换成数值型,并做加法运算.
CASE3: SELECT ‘cjy’+90;      结果为90,即若其中一方的字符型转换失败,mysql将其视为0.
CASE4: SELECT NULL+90;      结果为NULL.

通配符 % 和 _

%号表示 匹配任意多个字符,包括0个.
_ 号表示 匹配单个字符.
若不想让#或者_作为通配符,即想匹配#或者_,则可使用转义字符 \;或者用关键字ESCAPE,如:

SELECT DISTINCT last_name  
FROM employees  
WHERE last_name LIKE '\_!_%'  ESCAPE  '!'

安全等于 <=>

既可以判断普通数值型或字符串型,相当于 = ,也可以判断NULL值,如:

WHERE commission_pct IS NULL 相当于 WHERE commission_pct <=> NULL. 

ISNULL()函数

ISNULL(expr),若expr为NULL,则返回1,否则,返回0.

常见函数

常见字符函数

  • RIGHT/LEFT(str, n) 用于取字符串 str 右边/左边数起 n 个字符
  • CONCAT() 用于拼接字符串
SELECT CONCAT('Michael',' ', 'Jordan');
-> Michael Jordan
  • UPPER()用于将字符串中的字母全部转换成 写字母
  • LOWER()用于将字符串中的字母全部转换成 写字母
  • TRIM([{ BOTH | LEADING | TRAILING } [remstr] FROM] str)用于将指定字符去掉
SELECT TRIM(leading '*' from '!!!hitccc!!!');
-> hitccc!!!

SELECT TRIM(both '!' from '!!!hitccc!!!'); //不加分类符时默认为both
-> hitccc

SELECT TRIM(trailing '!' from '!!!hitccc!!!');
-> !!!hitccc
----------------
TRIM() 还可用于去掉空格,另 LTRIM() 去左边空格, RTRIM() 去右边空格 
  • REPLACE(expr_1, expr_2, expr_3) 用 expr_3 替换 expr_1 中的 expr_2
  • INSERT(原始字符串,开始位置,需要替换的字符数,替换字符串) *//开始位置最小为1,若替换的字符数为0,则替换字符串就会被插入其中,剩余的字符会后移. *
//replace函数
SELECT REPLACE('mysql is the best','mysql','sql server');
-> sql server is the best

//insert函数
SELECT INSERT('hello world!',1,5,'my');
-> my world!

SELECT INSERT('hello world!',7,0,'my ')
-> hello my world!
  • LPAD()和RPAD() 用于填充
SELECT lpad('hitccc',10,'*'); //其中,10为填充后的字符串长度
-> ****hitccc

SELECT rpad('hitccc',10,'*');
-> hitccc****
  • LENGTH() 用于返回字节长度
SELECT length('hitccc');  /*一个英文字符1字节,一个汉字3字节*/
-> 6
  • SUBSTR(str, num start, num length) 返回指定位置指定长度的字符子串
SELECT substr('hello world!',1,5);
-> hello
  • INSTR() 返回字符串中子字符串第一次出现的位置(不区分大小写) //与之类似的还有下面的POSITION()函数
SELECT instr('hitccc','c');
-> 4
  • POSITION(子字符串 IN 字符串型的字段) 用于找出字符串中子字符串的位置,若找不到,则返回0
SELECT vchar_fld FROM string_tb1;
-> This is a piece of cake. 

SELECT position('piece' IN vchar_fld) FROM string_tb1;
-> 11
  • QUOTE(str) 用单引号将整个字符串包含起来,并为字符串中本身的单引号增加转义字符
  • STRCMP(str_1,str_2) 用于比较两个字符串,根据字符串排序,类似于C语言中标准库里的strcmp()函数,⚠️MySQL里该函数不区分大小写.

常见数学函数

数字精度函数
  • ROUND(a,b) 用于四舍五入. //其中,b可以为负数,表示小数点左侧的取整 abs(b) 位.
SELECT round(-1.65);
-> -2

SELECT round(-1.65,1);
-> -1.7

SELECT round(17,-1);
-> 20
  • CEIL() 用于向取整
  • FLOOR() 用于向取整
  • TRUNCATE(a,b) 用于截断. //其中,b可以为负数,表示小数点左侧的截断位数.
SELECT truncate(-1.42424,2);
-> -1.42

SELECT TRUNCATE(17,-1);
-> 10  
  • SIGN(a) 用于返回a的符号,有-1,0,1.

  • ABS(a) 用于返回a的绝对值.

算术函数
  • MOD(a,b) 用于取模,即返回a%b. **//MySQL中可用它来处理实数,即a可以为实数. **
  • POW(a,b) 返回a的b次方

常见日期函数

  • NOW() 和CURRENT_TIMESTAMP() 均返回系统当前日期和时间
  • CURDATE() 返回系统当前日期
  • CURTIME() 返回系统当前时间
  • YEAR(), MONTH(), DAY(), HOUR(), SECOND()
  • MONTHNAME() 返回月份英文名
  • DATE_ADD() 为指定日期增加一段时间间隔并返回新的日期时间
SELECT date_add(current_date(),INTERVAL 5 year);
-> 2024-09-15

注:INTERVAL为关键字,时间间隔单位可取 second /minute /hour /day /year /month,另外,还可取较为特殊的hour_second,year_month……(如下)

SELECT date_add(NOW(), INTERVAL '3:30:12' hour_second);
-> 2019-09-16 00:31:42
  • DAYNAME() 返回输入日期是星期几
SELECT dayname('2019-10-01');
-> Tuesday
  • EXTRACT() 用于提取日期型数据中的子元素
SELECT extract(year FROM now());
-> 2019
  • DATEDIFF() 返回两个日期之间的天数,它会忽略日期中的时钟值,只看日期
SELECT datediff('2019-9-01','2019-10-01');
-> -30
  • STR_TO_DATE() 将字符通过指定的格式转换成日期
SELECT str_to_date('4-3 1989','%c-%d %Y');
-> 1989-04-03
  • DATE_FORMAT() 将日期转换成字符
SELECT date_format('2019/12/22','%Y年%m月%d日')-> 20191222
日期格式 对应描述
%a 缩写星期名
%c或者%m 月份序号(01~12)
%M 月名称(1月~12月)
%d 日序号(01~31)
%j 日在一年中的序号(01~366)
%W 星期名称(星期一~星期日)
%Y 4位数字的年份
%y 2位数字的年份
%H 小时(01~24)
%h 小时(01~12)
%i 分钟(00~59)
%s 秒钟(00~59)
%f 微秒(000000~999999)
%p A.M.或者P.M.

类型转换函数 CAST()

  • CAST(expression AS 类型 ) 将任何类型的值转换为具有指定类型的值

类型可为BINARY,CHAR,SIGNED,UNSIGNED,DATE,DATETIME,TIME等等.

SELECT cast('-1234.32' AS SIGNED INTEGER);
-> -1234

分组和聚集

分组

  • group by子句 可对数据进行分组操作,即

group by 字段名 可按字段名进行分组

  • having子句 和上述子句配套使用,作用类似于where子句,区别是 where子句作用范围是整个关系表,而having子句作用的是根据 group by子句所分好的组.所以having子句只能出现在 group by子句后面,不能单独出现.
One Tip:WITH ROLLUP

​ group by子句中可以增加WITH ROLLUP选项,作用是在原来分组的基础上再增加几行进行统计汇总,下面是一个具体例子.

SELECT `Grade`,`Class`,SUM(`Stu_num`)
FROM explain_rollup
GROUP BY Grade, Class WITH ROLLUP;
MySQL语法心得总结(不定期更新)_第1张图片

可以理解为从不同的维度再计算一下.

聚集函数

顾名思义,聚集函数是以分组单位,对分组中的所有行进行的特定操作.

⚠️:在使用这些聚集函数时,最好用显示分组方式,即用group by子句,否则可能会报错. 隐式分组即为整张表.

  • Max() 返回集合中的最大值
  • Min() 返回集合中的最小值
  • Avg() 返回集合中的平均值
  • Sum() 返回集合中所有值的和
  • Count() 返回集合中值的个数
Tips
  1. 可用 COUNT(DISTINCT 字段名) 的组合来查询分组的指定列中不同值的个数.

  2. 聚集函数中的参数可以是表达式.

  3. 对于Count()函数,Count(*) 不会忽略null值,即有多少行就返回多少行数,而Count(列名) 则会忽略该列名中为null值的那些行,返回的行数中不包括null值.

  4. 聚集函数不能用在where子句中,只能用在having子句中.

  5. 除Count()函数外,其他几个聚集函数会自动忽略null值

  6. Max()和Min()函数中的参数可以是字符串型数据日期型数据.字符串就是看字典序来确定大小,日期型数据就是根据时间的早晚来确定,越早越小.

连接

内连接

  • 关键字 inner join ,若不指定连接条件则退化为交叉连接. 在关键字on后给出连接条件,可为等值连接和非等值连接.

等值连接 A inner join B on A.列名 = B.列名;

非等值连接可为 不等号,between … and … 等.

e.g. A inner join B on A.列名 between B.列名1 and B.列名2

外连接

可分为左外连接右外连接和全外连接.

  • 左外连接 关键字 left [outer] join ,可理解为左边的表为主表,右边的表为副表,使用左外连接操作返回的结果中左表中原有的记录都要出现,右表中的列值可为null值.
  • 右外连接 关键字 right [outer] join ,意思和上面类似,此时右边的表决定结果集合中的行数.
  • 全外连接 关键字 full [outer] join很遗憾MySQL8.0暂不支持全外连接,使用这个关键字会报错. 我们可以用 左外连接+右外连接 这个组合来实现全外连接,即全外连接实际上就是左外连接和右外连接的并集.

交叉连接

  • 关键字 cross join ,其实本质就相当于笛卡尔积.

e.g. 若表A有m行记录,表B有n行记录,那么做 A cross join B 的操作结果会返回m*n行记录.

自然连接

  • 关键字 natural join ,不用给出连接条件,数据库服务器会自动找出两张表中列名相同的两列进行等值连接,若没有两列的列名是一样的,那么很抱歉,自然连接会自动退化成交叉连接,且系统不会报错.

条件逻辑—流程控制语句( IF和CASE )

IF语句

- IF(condition,a,b)
若condition为真,则返回a;否则,返回b. 

e.g.
SELECT last_name, commission_pct, if(isnull(commission_pct) = 1,'呵呵','哈哈') as 备注
from employees;

//上述SQL语句表示若员工奖金率为空值,则返回 ‘呵呵’,否则,返回 ‘哈哈’.

CASE语句

- 简单型case表达式:
CASE 字段名或表达式
when1 then 结果1
when2 then 结果2
when3 then 结果3
. . . 
else 结果N
end 

- 查找型case表达式:
CASE 
when 条件1 then 结果1
when 条件2 then 结果2
. . . 
else 结果N
end

查找型case表达式相较于第一种来说更加的灵活,简单型case表达式只能用于等式条件,即CASE后面的字段名活着表达式在下面对号入座,而查找型case表达式可以构造不等式条件. 第一种类似于C语言中switch语句.

⚠️ 上面两个表达式的返回表达式就是then后面的一个结果i.

下面给出一个《SQL学习指南》中的一个例子便于理解.
MySQL语法心得总结(不定期更新)_第2张图片

  • case表达式用途

    • 用于结果集转换,即将原来表中的一列取出作为行.
    • 用于聚合函数内,如SUM函数中的参数为一个case表达式,而case表达式返回表达式可条件选择.
    • 用于null值的处理和零值处理.
    • 用于存在性检查,如case表达式的其中一个when关键字后的条件为exists关联子查询,只要exists返回为真,就then真;else假.
    SELECT c.cust_id, c.fed_id, c.cust_type_cd,
    CASE
    WHEN EXISTS (SELECT * FROM account a
                WHERE a.cust_id = c.cust_id
                AND a.product_cd = 'CHK') THEN 'Y'
    ELSE 'N'
    END has_checking
    FROM customer c;
    
    MySQL语法心得总结(不定期更新)_第3张图片

控制流函数IFNULL()

IFNULL(expr_1, expr_2) 函数用于判断 expr_1 是否为 NULL,如果为 NULL 则返回 expr_2 的值,如果不为 NULL 则返回 expr_1 的值. 如:

SELECT employee_id, IFNULL(commission_pct, 0) //表示若奖金率为NULL值,则返回0. 
FROM employees;  

事务

  • 概念:事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列组成.
  • 特性:ACID
    • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行.
    • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束.
    • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行.
    • 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中.

注:上述特性引用自维基百科

  • MySQL在一个新会话下默认开启自动提交模式,使用set autocommit = 0可以关闭自动提交,这是就可以用rollback回滚了.

  • 事务保存点:类似于断点的意思,操作者可回滚到指定事务保存点而不是事务启动位置.

    SAVEPOINT sp_name;
    
    //回滚时
    ROLLBACK TO SAVEPOINT sp_name;
    

索引

⚠️索引是在存储引擎层面实现的,不同的存储引擎支持不同的索引类型. MySQL一般默认索引类型为B树索引.

MySQL主要有以下三种索引类型.

  • B-Tree索引 (B树理解)
  • Hash索引 ( Memory引擎默认使用索引,基于哈希表 )
  • FULLTEXT索引( InnoDB从MySQL5.6开始也支持全文索引了 )

创建普通索引

//为某一列创建索引,可创建 单列索引,也可创建 多列索引.
ALTER TABLE table_name
ADD INDEX index_name(列名1,列名2...,列名N);

e.g.
ALTER TABLE `department`
ADD INDEX dept_name_idx(name);

注:当表被创建的时候,MySQL会自动为主键列创建索引.

创建唯一索引

当某一列的值不允许出现重复值,但是该字段又不是主键时,我们可以为该列创建一个唯一索引.

ALTER TABLE table_name
ADD UNIQUE INDEX index_name(列名);

注:ERROR 1062 即此产生.

查看索引

SHOW INDEX FROM table_name;

删除索引

//删除某一索引
ALTER TABLE table_name
DROP INDEX index_name;
or
DROP INDEX index_name ON table_name;

⚠️(1)为被外键约束引用的列创建索引;(2)为那些被频繁检索的列创建索引.

约束

约束一般有以下几种类型:

  • 主键约束

    CONSTRAINT [约束名] PRIMARY KEY (列名) //可多列
    
  • 外键约束

    CONSTRAINT [约束名] FOREIGN KEY (列名) REFERENCES refer_table_name(列名) [ON UPDATE/DELETE CASCADE]  //可多列
    

    注:在没有选级联更新选项的时候,外键约束不允许参照这个字段的表插入的记录中所参照的那一列有它没有的值;若有级联更新,则可行,且所产生的变化会传播相关联的表. 级联删除同.

  • 唯一性约束

    CONSTRAINT [约束名] UNIQUE (列名) //可多列
    
  • 检查约束

    CONSTRAINT [约束名] CHECK (condition)
    
  • 空值约束

    列名 NOT NULL
    

创建约束

方式一:在创建表的时候就用上面语句添加约束
方式二:若表已经创建完,之后想添加约束在,则如下语句
ALTER TABLE table_name
ADD CONSTRAINT ...;		//同上面的语句

删除约束

ALTER TABLE table_name
DROP CONSTRAINT 约束名;

//删除主键约束时直接
ALTER TABLE table_name
DROP PRIMARY KEY;

视图

视图不涉及数据存储,为虚拟表.

创建视图/更新视图

CREATE OR REPLACE VIEW 视图名 AS (
  SELECT ...
  FROM ...
  WHERE ...);

向视图中插入/删除数据,结果会体现到(base table)基表上.

⚠️以下几种情况下视图不可更新:

  • 含聚合函数
  • 含group by或者having子句
  • 含union或union all
  • 含distinct
  • 多表连接的视图使用了外连接
  • 含子查询
  • ALGORITHM = TEMPTABLE (MySQL默认是MERGE算法)
  • 含计算列

另外,注意当多表连接生成的视图时,你插入数据一次只能更新其中一个基表中的列,不能多表插入!!!

删除视图

DROP VIEW 视图名;

元数据

数据的数据,是数据的抽象描述. 类似于模式是对关系表的抽象描述.

information_schema

在MySQL中用information_schema数据库来提供元数据,可用以下命令来查看该数据库中的各种视图的结构,从中知道里面的每张视图存了什么.

use information_schema;
show tables;
desc table_name;

较为常用的有有以下这几个表.

Schema -----数据库信息

Tables -----表和视图的信息

Columns -----表和视图的列信息

Statistics -----索引信息

Schema/Table/Column_Privileges -----数据库/表/列 权限分配

Views -----视图信息

Triggers -----触发器信息

Engines -----可用存储引擎信息

使用元数据

  • 可用来模式生成脚本

    MySQL语法心得总结(不定期更新)_第4张图片

推荐书籍

  • MySQL必知必会
  • MySQL技术内幕:InnoDB存储引擎

你可能感兴趣的:(数据库,#MySQL)