第一章 MySQL基础总结笔记

全球访问量最大的20家网站,他们分别使用了什么数据库呢,绝大多数使用mysql,有两个完整live.com和bing使用的是mssql,并不是他们使用不了mysql,而是他要支持自己的数据库。

在国外可能挺多使用mssql或者oracle的,但是在过能,在去IOE的大背景下,包括银行在内的很多传统公司慢慢都在像mysql转型,不过其中有个老大不掉的公司,中国电力,依然使用oracle,在十年的时间仅仅在oracle的使用上,中国电力就支出390几个亿,平均一年30,40个亿,它有钱,如果你所在公司随随便便也能拿个几百个亿,那你也用oracle吧

一、MySQL安装

在第一期,课程是在windows安装的mysql,但第二期,同学们都有linux基础了,所以,第二期会在linux上使用,没有使用过linux的同学先去看下第一期peter老师的视频。

1、准备工作

  Linux 使用的版本是centos 7,为方便起见,先把防火墙关闭,配置好网络,在安装部分,会分成两部分讲,首先讲单实例安装,也就是一台服务器上就装一个mysql,接下来就多实例安装,在一个服务器上安装2个甚至多个mysql。

2、单实例安装

安装需要的依赖

yum install -y libaio

2.1、解压mysql到/usr/local目录:

首先复制文件到/usr/local/下面,然后解压

cp /soft/mysql-5.7.9-linux-glibc2.5-x86_64.tar.gz  /usr/local/

shell> cd /usr/local
shell> tar -zxvf mysql-5.7.9-linux-glibc2.5-x86_64.tar.gz

2.1、添加用户与组

shell> groupadd mysql

shell> useradd -r -g mysql mysql

// 建立一个mysql的软连接

shell> ln -s /usr/local/mysql-5.7.9-linux-glibc2.5-x86_64 mysql

shell> cd mysql

shell> mkdir mysql-files

shell> chmod 770 mysql-files

2.3、改变一个目录的所有人属性并同时改变改目录下所有文件的属性 

shell> chown -R mysql .

// 改变文件的群组 

shell> chgrp -R mysql .

// 密码:ry4Plm(Oy*jq(注意第一次安装出现失败后,继续从该命令开始安装)

shell> bin/mysqld --initialize --user=mysql 

shell> bin/mysql_ssl_rsa_setup

shell> chown -R root .

// 在mysql创建一个data目录,用于存放数据文件。执行以下命令

shell> chown -R mysql data mysql-files

2.4、启动服务

出现错误,原因是/etc/my.cnf文件没有权限

shell> bin/mysqld_safe --user=mysql &

# Next command is optional

shell> cp support-files/mysql.server /etc/init.d/mysql.server

2.5、设置开机启动项:

查看启动项命令:chkconfig --list

mysql>FLUSH PRIVILEGES;     #刷新权限

 

配置开启启动

chkconfig mysql.server on

chkconfig --list

2.6、配置环境变量: 

查看命令:vi /etc/profile(添加下面内容)

export PATH=/usr/local/mysql/bin:$PATH

2.7、登陆设置密码

在mysql系统外,使用mysqladmin(进入到/var/local/mysql/bin)。

登陆:mysql -uroot -p'ry4Plm(Oy*jq'

修改密码:set password = 'root';

2.8、授权访问

在 Linux 下为了安全,默认是不允许 MySQL 服务器本机以外的机器访问 MySQL 数据库服务的,因此需要重新授权 root 账号。方便其他机器远程访问 MySQL 服务器,MySQL 命令如下:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root1234%'

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;

flush privileges;  

2.9、测试查询

这样就可以允许从其他机器用 root 账号远程登录 MySQL 服务器了,可以用下面的 MySQL 命令来验证一下:

mysql> use mysql; 

mysql> select host,user from user; 

启动的时候可能会报错

这是因为mysql启动的时候需要配置文件,而在安装centos的时候,哪怕是mini版本都会有个默认的配置在/etc目录中:

/usr/local/mysql/bin/mysqld --verbose --help |grep -A 1 'Default options'

Default options are read from the following files in the given order:

/etc/my.cnf  /etc/mysql/my.cnf  /usr/local/mysql/etc/my.cnf ~/.my.cnf

 

Mysql启动的时候会以上面所述的顺序加载配置文件

注意:如果报错,先重命名my.cnf文件

3、多实例安装

以前一些很low的方法是,解压两个mysql,分别放到不同文件夹,其实在mysql中已经考虑到了多实例安装的情况。也有相应的脚本命令的支持。

现在要求装两个mysql 一个3307,3308

3.1、解压到/usr/local/ 下面, 更名mysql

cp /soft/mysql-5.7.9-linux-glibc2.5-x86_64.tar.gz  /usr/local/

tar xzvf mysql-5.7.9-linux-glibc2.5-x86_64.tar.gz

mv /usr/local/mysql-5.7.9-linux-glibc2.5-x86_64 /usr/local/mysql

3.2、新建 /etc/my.cnf 配置如下

vi /etc/my.cnf

[mysqld]
sql_mode = "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER"

[mysqld_multi]
mysqld = /usr/local/mysql/bin/mysqld_safe
mysqladmin = /usr/local/mysql/bin/mysqladmin
log = /var/log/mysqld_multi.log

[mysqld1]
server-id = 11
socket = /tmp/mysql.sock1
port = 3307
datadir = /data1
user = mysql
performance_schema = off
innodb_buffer_pool_size = 32M
skip_name_resolve = 1
log_error = error.log
pid-file = /data1/mysql.pid1

[mysqld2]
server-id = 12
socket = /tmp/mysql.sock2
port = 3308
datadir = /data2
user = mysql
performance_schema = off
innodb_buffer_pool_size = 32M
skip_name_resolve = 1
log_error = error.log
pid-file = /data2/mysql.pid2

3改变文件夹权限

创建mysql用户和用户组:

groupadd mysql

useradd mysql -g mysql

chown -R mysql:mysql mysql/

chmod -R 755 mysql/

4)建立一个mysql的软连接

shell> ln -s /usr/local/mysql-5.7.9-linux-glibc2.5-x86_64 mysql

shell> cd mysql

shell> mkdir mysql-files

shell> chmod 770 mysql-files

注意:安装依赖包(非必须)

yum -y install make gcc-c++ cmake bison-devel ncurses-devellibaio libaio-devel

5)创建2个数据目录并赋权限

mkdir /data1

mkdir /data2

chown mysql.mysql /data1

chown mysql.mysql /data2

6)初始化各个实例:

初始化完后会在日志中生成密码,记得保存,一会要用。

/usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/data1

/usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/data2

7)开启各实例的SSL连接(可选)

/usr/local/mysql/bin/mysql_ssl_rsa_setup --user=mysql --basedir=/usr/local/mysql --datadir=/data1

/usr/local/mysql/bin/mysql_ssl_rsa_setup --user=mysql --basedir=/usr/local/mysql --datadir=/data2

 

8添加环境变量

a、在文件最后面添加内容:

vi /etc/profile

## SETUP MYSQL’S PATH

export MYSQL_HOME=/usr/local/mysql

export PATH=${MYSQL_HOME}/bin:$PATH

b、  使修改的配置文件生效:

source /etc/profile

9)配置开机启动

复制多实例脚本到服务管理目录下

cp /usr/local/mysql/support-files/mysqld_multi.server /etc/init.d/mysqld_multid

或者:mv /data/soft/mysql/support-files/mysql.server /etc/init.d/mysqld_multid

给予脚本可执行权限:

chmod +x /etc/init.d/mysqld_multid

加入service服务管理:

chkconfig --add mysqld_multid

显示服务列表:

chkconfig --list

如果3,4,5都是开的就说明是自启设置成功。没有的话,就执行

chkconfig --level 345 mysqld_multid on

chkconfig mysqld_multid on(实现不了)

10)查看状态:

/etc/init.d/mysqld_multid report

这个时候发现还需要perl的环境,安装

yum -y install perl perl-devel

执行结果:

/etc/init.d/mysqld_multid report

Reporting MySQL servers

MySQL server from group: mysqld1 is not running

MySQL server from group: mysqld2 is not running

 

附加介绍一下Linux系统的运行级的概念:

Linux OS 将操作 环境分为以下7个等级,即

0:关机

1:单用户模式(单用户、无网络)

2:无网络支持的多用户模式(多用户、无网络)

3:有网络支持的多用户模式(多用户、有网络)

4:保留,未使用

5:有网络支持有X-Window支持的多用户模式(多用户、有网络、X-Window界面)

6:重新引导系统,即重启

 

11、 启动各个实例 :

mysqld_multi start

/etc/init.d/mysqld_multid report

Reporting MySQL servers

MySQL server from group: mysqld1 is running

MySQL server from group: mysqld2 is running

查看实例的监听端口:ss -tulpn|grep mysqld

[root@bogon local]# ss -tulpn|grep mysqld

tcp    LISTEN     0      80    :::3307       :::*       users:(("mysqld",pid=10921,fd=16))

tcp  LISTEN    0     80    :::3308       :::*       users:(("mysqld",pid=10922,fd=16))

 连接实例:

mysql -u root -S /tmp/mysql.sock1 -p -P3307

或者:sudo mysql -S /tmp/mysql.sock1 -p前面生成的密码

分别修改密码:set password = '123456%';

 

12、允许远程连接mysql:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456%';

flush privileges; 

其中,root 是用户名,% 表示所有人都可以访问,password是密码。

13、最后测试查询:

mysql> use mysql; 

mysql> select Host,User,max_user_connections,password_last_changed,account_locked from user; 

第二个MySQL节点3308,设置如下:

mysql -u root -S /tmp/mysql.sock2 -p -P3308(同上)

set password = '123456%';

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY ''123456%' WITH GRANT OPTION;

flush privileges; 

 

 

二、CentOS 7防火墙设置

CentOS 7 使用firewalld代替了原来的iptables,使用方法如下:

1、关闭防火墙

systemctl stop firewalld.service            #停止firewall

systemctl disable firewalld.service        #禁止firewall开机启动

2、开启端口

firewall-cmd --zone=public --add-port=80/tcp --permanent

命令含义

--zone #作用域
--add-port=80/tcp #添加端口,格式为:端口/通讯协议
--permanent #永久生效,没有此参数重启后失效

3、重启防火墙

firewall-cmd --reload

其他常用命令:

 firewall-cmd --state                          ##查看防火墙状态,是否是running

firewall-cmd --reload                          ##重新载入配置,比如添加规则之后,需要执行此命令

firewall-cmd --get-zones                      ##列出支持的zone

firewall-cmd --get-services                    ##列出支持的服务,在列表中的服务是放行的

firewall-cmd --query-service ftp              ##查看ftp服务是否支持,返回yes或者no

firewall-cmd --add-service=ftp                ##临时开放ftp服务

firewall-cmd --add-service=ftp --permanent    ##永久开放ftp服务

firewall-cmd --remove-service=ftp --permanent  ##永久移除ftp服务

firewall-cmd --add-port=80/tcp --permanent    ##永久添加80端口 

iptables -L -n                                ##查看规则,这个命令是和iptables的相同的

man firewall-cmd                              ##查看帮助

更多命令,使用 firewall-cmd --help 查看帮助文件

CentOS 7.0默认使用的是firewall作为防火墙,使用iptables必须重新设置一下

3.1、直接关闭防火墙

systemctl stop firewalld.service          #停止firewall
systemctl disable firewalld.service    #禁止firewall开机启动

3.2、设置 iptables service

yum -y install iptables-services

如果要修改防火墙配置,如增加防火墙端口3306

vi /etc/sysconfig/iptables 

增加规则

-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT

保存退出后

systemctl restart iptables.service #重启防火墙使配置生效

systemctl enable iptables.service #设置防火墙开机启动

最后重启系统使设置生效即可。

CentOS 7防火墙服务FirewallD指南  http://www.linuxidc.com/Linux/2016-10/136431.htm

firewalld和iptables 详解  http://www.linuxidc.com/Linux/2017-03/141434.htm

CentOS7下Firewalld防火墙使用实例  http://www.linuxidc.com/Linux/2017-01/139637.htm

CentOS 7下FirewallD使用简介  http://www.linuxidc.com/Linux/2016-11/137093.htm

本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-11/148427.htm

 

三、Mysql权限

1、最简单的MySql权限  

最简单也是最高效的,如果解决新手们删库跑路的问题其实也是很简单的,对于正式库只给一个增删改查的权限,或者只给一个查询权限(是不是就解决了删库的可能性?)

使用Root用户,执行:

grant SELECT on hankin.* TO 'dev'@'192.168.42.%' IDENTIFIED BY '123' WITH GRANT OPTION;

很简单的一句sql,创建了一个dev的用户,密码为123,仅仅运行在网段为192.168.0.*的网段进行查询操作。再执行一条命令:

show grants for 'dev'@'192.168.42.%';

2、深入研究下MySQL权限

2.1、用户标识是什么

上面一句简单的SQL堪称完美的解决了程序员新手的删库跑路的问题,但是如果想面试给面试管留下好映像,上面的知识好像还不够,有必要好好深入研究下MySql的权限了。这里有个小的知识点需要先具备,在mysql中的权限不是单纯的赋予给用户的,而是赋予给”用户+IP”的。

比如dev用户是否能登陆,用什么密码登陆,并且能访问什么数据库等都需要加上IP,这样才算一个完整的用户标识,换句话说 'dev'@'192.168.0.168' 、'dev'@'127.0.0.1''dev'@'localhost' 这3个是完全不同的用户标识(哪怕你本机的ip就是192.168.0.168)。

2.2、用户权限所涉及的表

有了用户标识的概念接下来就可以看权限涉及的表了,这也是面试的时候加分项哦。有几张表需要谨记:

mysql.user,mysql.db,mysql.table_priv,mysql_column_priv

你可以熟悉其中的user表,甚至手动的改过里面的数据(不合规范哦!)

那这些表有什么用,和权限又有什么关系呢?

  • User的一行记录代表一个用户标识
  • db的一行记录代表对数据库的权限
  • table_priv的一行记录代表对表的权限
  • column_priv的一行记录代表对某一列的权限

2.3、测试:新建一个表account:

DROP TABLE IF EXISTS hankin.`account`;
CREATE TABLE hankin.`account` (
  `id` int(11) NOT NULL,
  `name` varchar(50) DEFAULT NULL,
  `balance` int(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_balance` (`balance`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO hankin.`account` VALUES ('1', 'lilei', '900');
INSERT INTO hankin.`account` VALUES ('2', 'hanmei', '100');
INSERT INTO hankin.`account` VALUES ('3', 'lucy', '250');
INSERT INTO hankin.`account` VALUES ('5', 'tom', '0');

mysql其实权限并不事特别low,权限的粒度甚至到了某一列上,举例来说,有个表account表。

对于前面创建的dev用户我不想让他访问balance列,但是id和name列是可以访问的,这样的需求在工作中不是没有。

在mysql维护工作中,做好权限管理是一个很重要的环节。下面对mysql权限操作进行梳理:

mysql的权限命令是grant,权限撤销的命令时revoke;

  • grant授权格式:grant 权限列表 on 库.表 to 用户名@'ip' identified by "密码";
  • revoke回收权限格式:revoke 权限列表 on 库.表 from 用户名@'ip';

下面通过一些例子说明:

2.4、用户授权


1)grant 普通数据用户,查询、插入、更新、删除 数据库中所有表数据的权利。

mysql> grant all on *.* to wang@'192.168.1.150' identified by "password";      //all等同于all privilege,其中的privileges可以省略

mysql> grant all privileges on *.* to wang@'192.168.1.%' identified by "123456";    //192.168.1.%表示一个网段

mysql> grant insert,select,update,delete,drop,create,alter on huanqiu.* to wang@'%' identified by "123456";

mysql> flush privileges      //授权之后,不要忘记更新权限表

2.5、查看权限


1)查看当前用户下所有的权限

mysql> show grants;

| Grants for root@localhost  

| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' WITH GRANT OPTION |

| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION                                                                        

2 rows in set (0.00 sec)

2)查看指定用户下的所有权限
USAGE是默认的初始状态,表示无任何权限!!
下面表示wang用户在192.168.1.0/24网段登陆本机mysql后,对huanqiu库下的所有表有insert, update, alter, delete, create, select的操作权限!

mysql> show grants for wang@'192.168.1.%';           //可以在select user,host,password from mysql.user执行结果中找对应的权限用户信息

| Grants for [email protected].%    

| GRANT USAGE ON *.* TO 'wang'@'192.168.1.%' IDENTIFIED BY PASSWORD '*678E2A46B8C71291A3915F92736C080819AD76DF' 

| GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER ON `huanqiu`.* TO 'wang'@'192.168.1.%'   

2 rows in set (0.00 sec)

例如grant select(id,name) on hankin.account to 'dev'@'192.168.42.%';

这时候可以在分别看下table_priv,column_priv的数据

 

3)revoke撤销权限

revoke跟grant语法差不多,只需要把关键字 “to” 换成 “from” 即可,并且revoke语句中不需要跟密码设置。

注意:revoke可以回收所有权限,也可以回收部分权限。

mysql> revoke all on *.* from wang@'192.168.1.150';                  

mysql> revoke all privileges on *.* from wang@'192.168.1.%';              

mysql> revoke insert,select,update,delete,drop,create,alter on huanqiu.* from wang@'%';

mysql> flush privileges   

注意事项:

1)grant, revoke用户权限后,该用户只有重新连接MySQL数据库,权限才能生效。
2)如果想让授权的用户,也可以将这些权限grant给其他用户,那么授权时需添加选项 "grant option"!
如下设置后,那么这个wang用户连接mysql后也可以将这些权限授予其他用户。

mysql授权表一共涉及到5个表,分别是user、db、host、tables_priv和columns_priv。
这5张表的内容和用途如下:

  • user表:user表列出可以连接服务器的用户及其口令,并且它指定他们有哪种全局(超级用户)权限。在user表启用的任何权限均是全局权限,并适用于所有数据库。例如,如果你启用了DELETE权限,在这里列出的用户可以从任何表中删除记录,所以在你这样做之前要认真考虑。
  • db表:db表列出数据库,而用户有权限访问它们。在这里指定的权限适用于一个数据库中的所有表。
  • host表:host表与db表结合使用在一个较好层次上控制特定主机对数据库的访问权限,这可能比单独使用db好些。这个表不受GRANT和REVOKE语句的影响,所以,你可能发觉你根本不是用它。
  • tables_priv表:tables_priv表指定表级权限,在这里指定的一个权限适用于一个表的所有列。
  • columns_priv表:columns_priv表指定列级权限。这里指定的权限适用于一个表的特定列。

REVOKE SELECT on hankin.* from 'dev'@'192.168.42.%';

你使用dev登陆查询试试

你再要查询所有记录?不好意思不让查,而你查询id,name查询又是可以了。

 

3、Mysql的角色

 3.1、准备工作

  MySql基于”用户+IP”的这种授权模式其实还是挺好用的,但如果你使用Oracle、PostgreSQL、SqlServer你可能会发牢骚,这样对于每个用户都要赋权的方式是不是太麻烦了,如果我用户多呢?有没有角色或者用户组这样的功能呢?在mysql5.7开始才正式支持这个功能,而且连mysql官方把它叫做“Role Like”(不是角色,长得比较像而已)。

那在5.7中怎么玩这个不像角色的角色呢?

show variables like "%proxy%"

你得先把check_proxy_users,mysql_native_password_proxy_users这两个变量设置成true才行

set GLOBAL check_proxy_users =1;

set GLOBAL mysql_native_password_proxy_users = 1;

当然,你也可以把这两个配置设置到my.cnf中

创建一个角色

create USER 'dev_role';

可能被你发现了,我这里创建得是个user,为了稍微像角色一点点,我给这user取名叫dev_role,而且为了方便也没用使用密码了。

创建2个开发人员账号:

create USER 'zhangsan';

create USER 'lisi';

这两个用户我也没设置密码,把两个用户加到组里面

grant proxy on 'dev_role' to 'zhangsan';

grant proxy on 'dev_role' to 'lisi';

可以看下其中一个用户的权限:

show GRANTS for zhangsan;

GRANT USAGE ON *.* TO 'zhangsan'@'%'

GRANT PROXY ON 'dev_role'@'%' TO 'zhangsan'@'%'

注意:如果你是远程链接,你可能会收获一个大大的错误,你没有权限做这一步,这个时候你需要再服务器上执行一条

 GRANT PROXY ON ''@'' TO 'root'@'%' WITH GRANT OPTION;

给角色dev_role应该有的权限:

有了用户了,这用户也归属到了dev_role这角色下面,那接下来要做的就很简单了,根据业务需求给这角色设置权限就好了(需要在服务器上执行)

grant select(id,name) on hankin.account to 'dev_role';

测试:现在使用zhangsan用户登陆系统试试

select id ,name from hankin.account;

你可能又会问,这种角色的权限是存哪的呢?

 

四、MySql数据类型

1、Int类型

类型

字节

最小值

最大值

 

 

(带符号的/无符号的)

(带符号的/无符号的)

TINYINT

1

-128

127

 

 

0

255

SMALLINT

2

-32768

32767

 

 

0

65535

MEDIUMINT

3

-8388608

8388607

 

 

0

16777215

INT

4

-2147483648

2147483647

 

 

0

4294967295

1.1、有无符号

在项目中使用BIGINT,而且是有符号的。

create table test_unsigned(a int unsigned, b int unsigned);

insert into test_unsigned values(1, 2);

select b - a from test_unsigned;

select a - b from test_unsigned;  --运行出错

> 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '--运行出错' at line 1

> 时间: 0s

1.2、INT(N)是什么?

create table test_int_n(a int(4) zerofill);

insert into test_int_n values(1);

insert into test_int_n values(123456);

  • int(N)中的 N 是显示宽度,不表示存储的数字的长度的上限。
  • zerofill 表示当存储的数字长度< N时,用数字0填充左边,直至补满长度N。
  • 当存储数字的长度超过N时,按照实际存储的数字显示。

1.3、自动增长的面试题

这列语法有错误吗?

create table test_auto_increment(a int auto_increment);

> 1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key

> 时间: 0.001s

create table test_auto_increment(a int auto_increment primary key);  -- 插入OK

以下结果是什么?

insert into test_auto_increment values(NULL);

insert into test_auto_increment values(0);

insert into test_auto_increment values(-1);

insert into test_auto_increment values(null),(100),(null),(10),(null)

总结:插入null索引会自动增加,插入0,索引也会增加但不是0,插入负数成功

2、字符类型

类型

说明

N的含义

是否有字符集

最大长度

CHAR(N)

定长字符

字符

255

VARCHAR(N)

变长字符

字符

16384

BINARY(N)

定长二进制字节

字节

255

VARBINARY(N)

变长二进制字节

字节

16384

TINYBLOB(N)

二进制大对象

字节

256

BLOB(N)

二进制大对象

字节

16K

MEDIUMBLOB(N)

二进制大对象

字节

16M

LONGBLOB(N)

二进制大对象

字节

4G

TINYTEXT(N)

大对象

字节

256

TEXT(N)

大对象

字节

16K

MEDIUMTEXT(N)

大对象

字节

16M

LONGTEXT(N)

大对象

字节

4G

排序规则

select 'a' = 'A';  -- 查询结果:1

create table test_ci (a varchar(10), key(a));

insert into test_ci values('a');

insert into test_ci values('A');

select * from test_ci where a = 'a';   -- 结果是什么?两条数据都查询成功

set names utf8mb4 collate utf8mb4_bin;

3、时间类型

日期类型

占用空间

表示范围

DATETIME

8

1000-01-01 00:00:00 ~ 9999-12-31 23:59:59

DATE

3

1000-01-01 ~ 9999-12-31

TIMESTAMP

4

1970-01-01 00:00:00UTC ~ 2038-01-19 03:14:07UTC

YEAR

1

YEAR(2):1970-2070, YEAR(4):1901-2155

TIME

3

-838:59:59 ~ 838:59:59

datatime与timestamp区别

create table test_time(a timestamp, b datetime);

insert into test_time values (now(), now());

select * from test_time;

查询结果:2019-06-20 22:04:59 2019-06-20 22:04:59

select @@time_zone;

查询结果:SYSTEM

set time_zone='+00:00';

select * from test_time;

查询结果:2019-06-20 14:04:59 2019-06-20 22:04:59

 

五、Mysql数据类型-JSON类型

 

1、JSON入门

 1.1、新建表

 create table json_user (
     uid int auto_increment,
     data json,
     primary key(uid)
 );

1.2、插入数据

insert into json_user values (null, '{ "name":"lison","age":18,"address":"enjoy" }' );

insert into json_user values (null,'{"name":"james","age":28,"mail":"[email protected]"}');

查询结果:

1 {"age": 18, "name": "张三", "address": "陕西西安"}

2 {"age": 28, "mail": "[email protected]", "name": "lisi"}

2、JSON函数

2.1、json_extract 抽取

select json_extract('[10, 20, [30, 40]]', '$[1]');

Select json_extract(data, '$.name'), json_extract(data, '$.address')  from hankin.json_user;

 

2.2、JSON_OBJECT 将对象转为json

select json_object("name", "wangwu", "email", "wangwu.com", "age",35);

mysql> select json_object("name", "wangwu", "email", "wangwu.com", "age",35);

| json_object("name", "wangwu", "email", "wangwu.com", "age",35) |
| {"age": 35, "name": "wangwu", "email": "wangwu.com"}           |
1 row in set (0.00 sec)

insert into hankin.json_user values ( null, json_object("name", "wangwu", "email", "wangwu.com", "age",35) );

2.3、json_insert 插入数据

语法:JSON_INSERT(json_doc, path, val[, path, val] ...)

set @json = '{ "a": 1, "b": [2, 3]}';

select json_insert(@json, '$.a', 10, '$.c', '[true, false]');

update hankin.json_user set data = json_insert(data, "$.address_2", "xiangxue") where uid = 1;

2.4、json_merge 合并数据并返回

select json_merge('{"name": "enjoy"}', '{"id": 47}');

select json_merge(json_extract(data, '$.address'), json_extract(data, '$.address_2')) from hankin.json_user where uid = 1;

 

其他函数参考如下地址:

https://dev.mysql.com/doc/refman/5.7/en/json-function-reference.html

JSON 类型数据本身 无法直接 创建索引,需要将需要索引的 JSON数据 重新 生成虚拟列(Virtual Columns) 之后,对 该列 进行 索引

create table test_inex_1(
    data json,
    gen_col varchar(10) generated always as (json_extract(data, '$.name')),
    index idx (gen_col)

);
insert into test_inex_1(data) values ('{"name":"king", "age":18, "address":"cs"}');
insert into test_inex_1(data) values ('{"name":"peter", "age":28, "address":"zz"}');

疑问:这条sql查询的结果是?

select json_extract(data,"$.name") as username from test_inex_1 where gen_col="king";

执行结果:Empty set (0.00 sec)

select json_extract(data,"$.name") as username from test_inex_1 where gen_col='"king"';

explain select json_extract(data,"$.name") as username from test_index_1 where gen_col="king";

示例:

自己查阅官方文档,建立虚拟列,这个列查询的时候不需要加上“”符号

create table test_index_2 (
    data json,
    gen_col varchar(10) generated always as ( json_unquote( json_extract(data, "$.name"))),
    key idx(gen_col)
);
insert into test_index_2(data) values ('{"name":"king", "age":18, "address":"cs"}');
insert into test_index_2(data) values ('{"name":"peter", "age":28, "address":"zz"}');

select json_extract(data,"$.name") as username from test_index_2 where gen_col="king";

查询结果:king 带有双引号。

答案:通过使用JSON_UNQUOTE来解决这个问题

SELECT json_extract(data,"$.name"),JSON_UNQUOTE(data->'$.name') from test_index_2 where gen_col="king";

猜你喜欢

转载自blog.csdn.net/m0_37661458/article/details/93142285