全球访问量最大的20家网站,他们分别使用了什么数据库呢,绝大多数使用mysql,有两个完整live.com和bing使用的是mssql,并不是他们使用不了mysql,而是他要支持自己的数据库。
在国外可能挺多使用mssql或者oracle的,但是在过能,在去IOE的大背景下,包括银行在内的很多传统公司慢慢都在像mysql转型,不过其中有个老大不掉的公司,中国电力,依然使用oracle,在十年的时间仅仅在oracle的使用上,中国电力就支出390几个亿,平均一年30,40个亿,它有钱,如果你所在公司随随便便也能拿个几百个亿,那你也用oracle吧
在第一期,课程是在windows安装的mysql,但第二期,同学们都有linux基础了,所以,第二期会在linux上使用,没有使用过linux的同学先去看下第一期peter老师的视频。
Linux 使用的版本是centos 7,为方便起见,先把防火墙关闭,配置好网络,在安装部分,会分成两部分讲,首先讲单实例安装,也就是一台服务器上就装一个mysql,接下来就多实例安装,在一个服务器上安装2个甚至多个mysql。
安装需要的依赖
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文件
以前一些很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 使用firewalld代替了原来的iptables,使用方法如下:
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动
firewall-cmd --zone=public --add-port=80/tcp --permanent
命令含义
--zone #作用域
--add-port=80/tcp #添加端口,格式为:端口/通讯协议
--permanent #永久生效,没有此参数重启后失效
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
最简单也是最高效的,如果解决新手们删库跑路的问题其实也是很简单的,对于正式库只给一个增删改查的权限,或者只给一个查询权限(是不是就解决了删库的可能性?)
使用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.%';
上面一句简单的SQL堪称完美的解决了程序员新手的删库跑路的问题,但是如果想面试给面试管留下好映像,上面的知识好像还不够,有必要好好深入研究下MySql的权限了。这里有个小的知识点需要先具备,在mysql中的权限不是单纯的赋予给用户的,而是赋予给”用户+IP”的。
比如dev用户是否能登陆,用什么密码登陆,并且能访问什么数据库等都需要加上IP,这样才算一个完整的用户标识,换句话说 'dev'@'192.168.0.168' 、'dev'@'127.0.0.1'与'dev'@'localhost' 这3个是完全不同的用户标识(哪怕你本机的ip就是192.168.0.168)。
有了用户标识的概念接下来就可以看权限涉及的表了,这也是面试的时候加分项哦。有几张表需要谨记:
mysql.user,mysql.db,mysql.table_priv,mysql_column_priv
你可以熟悉其中的user表,甚至手动的改过里面的数据(不合规范哦!)
那这些表有什么用,和权限又有什么关系呢?
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;
下面通过一些例子说明:
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 //授权之后,不要忘记更新权限表
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张表的内容和用途如下:
REVOKE SELECT on hankin.* from 'dev'@'192.168.42.%';
你使用dev登陆查询试试
你再要查询所有记录?不好意思不让查,而你查询id,name查询又是可以了。
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;
你可能又会问,这种角色的权限是存哪的呢?
类型 |
字节 |
最小值 |
最大值 |
|
|
(带符号的/无符号的) |
(带符号的/无符号的) |
TINYINT |
1 |
-128 |
127 |
|
|
0 |
255 |
SMALLINT |
2 |
-32768 |
32767 |
|
|
0 |
65535 |
MEDIUMINT |
3 |
-8388608 |
8388607 |
|
|
0 |
16777215 |
INT |
4 |
-2147483648 |
2147483647 |
|
|
0 |
4294967295 |
在项目中使用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
create table test_int_n(a int(4) zerofill);
insert into test_int_n values(1);
insert into test_int_n values(123456);
这列语法有错误吗?
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,插入负数成功
类型 |
说明 |
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;
日期类型 |
占用空间 |
表示范围 |
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
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.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";