关系型数据库: sql数据库
非关系型数据库: nosql数据库,not only sql数据库
关系型数据库:数据拥有固定的存储结构,通过库--表--行--列的方式存储,存储时会有表的结构化关系,过程如下:解析sql语句--连接层--磁盘存取--结构化成表,;
优势:1.容易理解,二维表的结构非常贴近现实世界,二维表格,容易理解;
2.使用方便,通用的sql语句使得操作关系型数据库非常方便;
3.易于维护,数据库的ACID属性,大大降低了数据冗余和数据不一致的概率;
非关系型数据库:非关系型数据库,就是为了加快客户端的访问速度才出现的,因为所有的非关系型数据库都是尽可能的将数据放到内存当中;非关系型数据库是以key:value的形式存储的;
Mysql整体架构:
1.连接池:最上层负责和客户端进行连接,比如jdbc,odbj这样的数据库连接的API,在这一层有连接池的概念,类似于线程池,连接池可以同时处理很多个数据库请求。同时这一层有SSL的安全概念,可以确保连接是安全的;
2.SQL接口:当SQL语句进入MySQL后,会先到SQL接口中,这一层是封装层,将传过来的SQL语句拆散,将底层的结果封装成SQL的数据格式;
3.解析器:这一层负责将SQL语句进行拆分,验证,如果语句有问题那么就返回错误,如果没问题就继续向下执行;
4.优化器:对SQL查询的结果优化处理,产生多种执行计划,最终数据库会选择最优化的方案去执行,尽快返会结果。比如select a,b from c where d。在这里会先查询c表中符合d的数据并将他们的ab项进行投影,返回结果,并不会直接把整张表查出来;
5.缓存:对要查询的SQL语句进行hash后缓存,如果下一次是相同的查询语句,则在SQL接口之后直接返回结果;
6.存储引擎:MySQL有很多种存储引擎,每一种存储引擎有不同的特性,他们负责组织文件的存放形式,位置,访问文件的方法等等。比较常用的有innoDB,MyISAM,MEMORY等;
7.文件系统:真正存放物理文件的单位;
(1)在mysql官网下载mysql:
本次实验用的是mysql5.7.12 和 boost文件(必须要有)
https://downloads.mysql.com/archives/get/p/23/file/mysql-boost-5.7.12.tar.gz
https://jaist.dl.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.bz2
(2)使用wget命令安装进行下载
(3)安装之后将boost文件放入/usr/local/boost
然后修改文件/etc/profile
echo "export PATH=$PATH:/usr/local/mysql/bin/" >>/etc/profile
source /etc/profile环境变量生效
(4)开始编译安装mysql
yum -y install gcc gcc-c++ ncurses bison libgcrypt perl cmake ncurses-devel
yum -y remove mysql-* boost-* #####安装依赖包
[root@my ~]# groupadd mysql
[root@my ~]# useradd -r -g mysql mysql
[root@my ~]# tar zxvf mysql-5.7.12.tar.gz -C /usr/src/
[root@my ~]# cd /usr/src/mysql-5.7.12/ ##编译多次时,需要删除CMAKE的缓存,rm -rf /usr/src/mysql-5.7.12/CMakeCache.txt
[root@my mysql-5.7.12]# cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/usr/local/mysql/data -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DMYSQL_TCP_PORT=3306 -DMYSQL_USER=mysql -DWITH_MYISAM_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 -DWITH_MEMORY_STORAGE_ENGINE=1 -DENABLE_DOWNLOADS=1 -DDOWNLOAD_BOOST=1 -DWITH_BOOST=/usr/local/boost -DSYSCONFDIR=/etc注释:
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql [MySQL安装的根目录]
-DMYSQL_DATADIR=/mydata/mysql/data [MySQL数据库文件存放目录]
-DDEFAULT_CHARSET=utf8 [设置默认字符集为utf8]
-DDEFAULT_COLLATION=utf8_general_ci [设置默认字符校对]
-DMYSQL_TCP_PORT=3306 [MySQL的监听端口]
-DMYSQL_USER=mysql [MySQL用户名]
-DWITH_MYISAM_STORAGE_ENGINE=1 [安装MySQL的myisam数据库引擎]
-DWITH_INNOBASE_STORAGE_ENGINE=1 [安装MySQL的innodb数据库引擎]
-DWITH_ARCHIVE_STORAGE_ENGINE=1 [安装MySQL的archive数据库引擎]
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 [安装MySQL的blackhole数据库引擎]
-DWITH_MEMORY_STORAGE_ENGINE=1 [安装MySQL的memory数据库引擎]
-DENABLE_DOWNLOADS=1 [编译时允许自主下载相关文件]
-DDOWNLOAD_BOOST=1 [允许下载BOOST]
-DWITH_BOOST=/usr/local/boost [指定系统中存在的BOOST]
-DSYSCONFDIR=/etc [MySQL配置文件所在目录]
-DWITH_READLINE=1 [MySQL的readline library]
-DMYSQL_UNIX_ADDR=/var/run/mysql/mysql.sock [MySQL的通讯目录]
-DENABLED_LOCAL_INFILE=1 [启用加载本地数据]
-DWITH_PARTITION_STORAGE_ENGINE=1 [启动mysql的分区存储结构]
-DEXTRA_CHARSETS=all [使MySQL支持所有的扩展字符]
-DWITH_DEBUG=0 [禁用调试模式]
-DMYSQL_MAINTAINER_MODE=0
-DWITH_SSL:STRING=bundled [通讯时支持ssl协议]
-DWITH_ZLIB:STRING=bundled [允许使用zlib library]
[root@my ~]#make && make install
[root@my ~]# echo "export PATH=$PATH:/usr/local/mysql/bin/" >>/etc/profile ###在/etc/profile中插入$PATH:/usr/local/mysql/bin/
[root@my ~]# source /etc/profile ##刷新配置文件就可以使用mysql命令
(4.2)进行mysql调优
[root@my ~]# chown -R mysql:mysql /usr/local/mysql
[root@my ~]# cp /usr/src/mysql-5.7.12/support-files/my-default.cnf /etc/my.cnf
[root@my ~]# cp /usr/src/mysql-5.7.12/support-files/mysql.server /etc/init.d/ ###此步执行完后就可以使用ysytemctl命令
[root@my ~]# chmod +x /etc/init.d/mysql.server
[root@my ~]# cat <>/usr/lib/systemd/system/mysqld.service ##编写服务控制脚本
[Unit]
Description=mysqldapi
After=network.target
[Service]
Type=forking
PIDFile=/usr/local/mysql/logs/mysqld.pid
ExecStart=/etc/init.d/mysql.server start
ExecReload=/etc/init.d/mysql.server restart
ExecStop=/etc/init.d/mysql.server stop
PrivateTmp=Flase
[Install]
WantedBy=multi-user.target
END
(4.3)初始化数据库服务
mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
(4.4)配置mysql配置文件(如果报pid的错误就使用此文件)
cat </etc/my.cnf
[mysqld]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
character_set_server=utf8
init_connect='SET NAMES utf8'
log-error=/usr/local/mysql/logs/mysqld.log
pid-file=/usr/local/mysql/logs/mysqld.pid
skip-name-resolve
END
(4.5)创建log文件,开启mysql,设置开机自启动
[root@my ~]# mkdir /usr/local/mysql/logs
[root@my ~]# chown mysql:mysql /usr/local/mysql/logs/
[root@my ~]# systemctl start mysqld
[root@my ~]# systemctl enable mysqld
Created symlink from /etc/systemd/system/multi-user.target.wants/mysqld.service to /usr/lib/systemd/system/mysqld.service.
[root@my ~]# netstat -utpln |grep mysqld
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 2885/mysqld
(4.6)测试连接访问数据库;
[root@my ~]# mysqladmin -u root -p password "123123" ##登录mysql设置密码
[root@my ~]# mysql -uroot -p123123
mysql> exit
PID报错
mysql密码重置
Sql语句分类:
日志记录类型:
类型 | 大小(字节) | 范围 | 格式 | 用途 |
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 时间值或持续时间 |
YEAR | 1 | 1901/2155 | YYYY | 混合日期和时间值 |
DATETIME | 8 | 1000-01-01 00:00:00/999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
TIMESTAMP | 4 | 1970-01-01 00:00:00/2073某年时 | YYYMMDDHHMMSS | 混合日期和时间值时间戳 |
[mysqld]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
character_set_server=utf8
init_connect='SET NAMES utf8'
log-error=/usr/local/mysql/logs/mysqld.log
pid-file=/usr/local/mysql/logs/mysqld.pid
skip-name-resolve
skip-grant-tables
select * from user \G;查看表内信息
update user set authentication_string=password('666666') where USER ='root';
updata user set 表头=密文加密('密码') where USER = 'root';
Structured Query Language:结构化查询语言
Sql是执行在客户端(windows在命令行下执行,linux在终端执行)下或者通过java代码执行在JDBC
linux
下在任何位置直接打开终端即可
windows
下使用各种客户端打开
登陆mysql命令 直接在终端下执行以下代码 然后输入密码
mysql -uroot -p
退出:
exit;
show databases;
create database db1;
指定字符集的创建格式 :create database 数据库名称 CHARACTER SET utf8;
create database db2 character set gbk;
show create database db1;
drop database db2;
use db2;
-表是数据库中的数据组成单位 类似于Java中的对象 表中的字段 对应对象中的属性
table
表名
(
字段
1名
字段类型,字段
2名
字段类型
);
create table person (name varchar(10),age int);
-在客户端中写完创建表的sql语句后客户端会把sql语句交给DBMS(MySql)DBMS解析后 会在数据库中创建语句中的表 和表中的字段 正在上传…重新上传取消
Structured Query Language:结构化查询语言
Sql是执行在客户端(windows在命令行下执行,linux在终端执行)下或者通过java代码执行在JDBC
linux
下在任何位置直接打开终端即可
windows
下使用各种客户端打开
登陆mysql命令 直接在终端下执行以下代码 然后输入密码
mysql -uroot -p
退出:
exit;
infornation_schema(信息_架构):存放mysql里其他库和表的信息的,保存着关于mysql服务器所维护的所有其它数据库的信息(入数据库名,数据库的表,表栏的数据类型与访问权限等)
MYSQL:主要存储数据库的用户,权限设置,关键字等mysql自己需要使用的控制和管理信息
performance_schema(性能架构):主要用于收集数据库服务器性能参数,并且库里的存储引擎均为PERFORMANCE_SCHEMA,而用户是不能创建存储引擎为PERFORMANCE_SCHEMA的表
sys: Sys库所有数据来源自performance_schema,目标是将performance_schema复杂度降低,让DBA能更好的阅读这个库里的内容,让DBA更快的了解DB的运行情况。
1.查看所有数据库命令:
show databases;
2. 创建数据库 通常一个项目只对应1个数据库 格式:create database 数据库名称;
create database db1;
3.指定字符集的创建格式 :create database 数据库名称 CHARACTER SET utf8;
create database db2 character set gbk;
4.查看数据库详情 -格式:show create database 数据库名称;
show create database db1;
5.删除数据库 -格式:drop database 数据库名称;
drop database db2;
6.选中进入数据库
use db2;
有时候会出现忘掉root密码等问题,这时就需要强制修改了
1.先进入/etc/my.cnf文件添加----
[mysqld]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
character_set_server=utf8
init_connect='SET NAMES utf8'
log-error=/usr/local/mysql/logs/mysqld.log
pid-file=/usr/local/mysql/logs/mysqld.pid
skip-name-resolve
2.重启服务
mysql> create table hero(id int,name char(10),type char(10));
alter table hero engine=myisam charset=utf8;
alter table hero add money int after name;
alter table hero change type hero_type varchar(30);
update hero set id=4 where id=1
rename table hero to heros;
alter table heros modify name varchar(10) after hero_type;
alter table heros drop money;
drop table heros;
create table hero (id int,name varchar(10),type varchar(10));
update usera set name='123' where math='ste.男';
insert into usera (name) values ('张翼德');###汉字一定要带两个单引号
show create table usera;
DESC 表名
INSERT INTO usera VALUES ('123456789','司马懿','男','123岁','123');
####一定要注意格式,如果格式是int就无法插入汉字
delete from usera where name ='123'; 删除所有name为123的行
delete from usera;
truncate table user;
####两个命令都可以起到删除所有的效果,但是delete比truncate慢,遇到大型列表还是需要truncate
alter table usera ENGINE=MyISAM;
[mysqld]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
character_set_server=utf8
init_connect='SET NAMES utf8'
log-error=/usr/local/mysql/logs/mysqld.log
pid-file=/usr/local/mysql/logs/mysqld.pid
skip-name-resolve
default-storage-engine=MyISAM
像注册游戏时,经常出现此用户名已被使用或此用户已存在,这就是主键的作用
主键:当把表格的某一列设置成主键的时候,那么这一列中的数据是不可以重复的
每张表通常会有一个且只有一个主键 来表示每条数据的唯一性
主键其实是对某一个字段的 约束
create table user (用户id int,姓名 char(10),年龄 int,性别 char(5),是否工作 char(5),是否有犯罪前科 char(5));
insert into user values('1','张翼德','180','男','否','是'),('2','张亮','18','男','是','否');
alter table user modify 姓名 char(10) primary key;
alter table 表名 修改模式 列名 列格式 插入主键
再次插入时:
mysql> insert into user values('1','张翼德','180','男','否','是');
ERROR 1062 (23000): Duplicate entry '张翼德' for key 'PRIMARY'
alter table users drop primary key;
aletr table 表名 删除 主键;
create table asd (id int primary key,age int);
create table 表名 (列名 格式 主键,列名 格式);
create table student (id int primary key auto_increment,age int);
(2.2)实验阶段:最后id会自动添加
insert into student values(1,20);
##先添加一个id为1,值为80
后面再单独插入一个
insert into stident age values(80)
##最后进行查看
select * from student;
+----+------+
| id | age |
+----+------+
| 1 | 20 |
| 2 | 80 |
+----+------+
2 rows in set (0.00 sec)
非空约束
not
nullcreate table student (id int primary key auto_increment, age int not null);
create table 表名 (列名 格式 主键 自增 , 列名 格式 不允许空行);
create table user (
id int comment '用户的id',
age int comment '用户的年龄'
);
创建员工表(
emp
)
和
部门表(
dept
)
分别在两个表中插入几条数据
id
要进行主键约束并且自增
部门名称不能为
null
(1)先进行创建
##创建两张表
mysql> create table emp (
-> id int primary key auto_increment,
-> bumen varchar(20),
-> detpId int,
-> joinDate date
-> );
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> create table dpet (
id int primary key auto_increment,
name char(20) not null
);
##创建两个参数
insert into dpet (name) values ('财务');
insert into dpet (name) values ('市场');
##查看
mysql> select * from dpet;
+----+--------+
| id | name |
+----+--------+
| 1 | 财务 |
| 2 | 市场 |
+----+--------+
2 rows in set (0.00 sec)
##创建四个参数
insert into emp (name,detpId) values ('小明',1),('小红',1),('小白',2),('小绿',2);
##查看
mysql> select * from emp
-> ;
+----+--------+--------+----------+
| id | bumen | detpId | joinDate |
+----+--------+--------+----------+
| 1 | 小明 | 1 | NULL |
| 2 | 小红 | 1 | NULL |
| 3 | 小白 | 2 | NULL |
| 4 | 小绿 | 2 | NULL |
+----+--------+--------+----------+
4 rows in set (0.00 sec)
(2)统计市场部有多少人,财务部有多少人
mysql> select name,bumen from dpet,emp where dpet.id=emp.detpId;
+--------+--------+
| name | bumen |
+--------+--------+
| 财务 | 小明 |
| 财务 | 小红 |
| 市场 | 小白 |
| 市场 | 小绿 |
+--------+--------+
4 rows in set (0.01 sec)
##只查看市场部
mysql> select dpet.name, emp.bumen from dpet,emp where dpet.id=2 and emp..detpId=2;
+--------+--------+
| name | bumen |
+--------+--------+
| 市场 | 小白 |
| 市场 | 小绿 |
+--------+--------+
2 rows in set (0.00 sec)
##只查看财务部
mysql> select dpet.name, emp.bumen from dpet,emp where dpet.id=1 and emp..detpId=1;
+--------+--------+
| name | bumen |
+--------+--------+
| 财务 | 小明 |
| 财务 | 小红 |
+--------+--------+
2 rows in set (0.00 sec)
一个事务中包含多条sql语句,而且这些sql语句之间存在一定的关系
比如A用户有1000RMB,B用户也有1000RMB,A用户给B用户转500,那么A用户和B用户的RMB的总额为多少?2000
比如A用户有1000RMB,B用户有1000RMB,C用户也有1000RMB,A用户向B用户转500的同时(事务1),C用户也可以向B用户转500(事务2),事务1和事务2之间是互相隔离的
比如A用户有1000RMB,B用户也有1000RMB,A用户向B用户转500之后,这个钱将会永远生效、
隔离级别 |
作用 |
Serializable(串行化) |
避免脏读、不可重复读、幻读 |
Repeatable(可重复读) |
避免脏读、不可重复读 |
Read committed(读已提交) |
避免脏读 |
Read uncommitted(读未提交) |
none |
read-uncommitted read-committed repeatable-read serializable
mysql> select @@global.tx_isolation;
配置文件中,加入以下参数可修改
transaction-isolation = serializable
begin: |
开始事务,后边有多条数据库操作语句开始执行; |
commit: |
开始提交一个事务,对应前边的begin操作,将事务处理的结果保存到数据文件中; |
rollback: | 开始回滚一个事务,在begin和commit之间,将事务中的全部语句撤回,恢复到执行begin之前的数据状态 |
set autocommit = 0/1; | 禁用或开启自动提交,自动提交为退出mysql连接程序时,或者执行下一条DML语句; |
mysql> begin; ##开始事务
Query OK, 0 rows affected (0.00 sec)
mysql> insert into it values('php工程师','曹操','891878195409081198','本科','9000');
Query OK, 1 row affected (0.00 sec)
mysql> commit; ##提交事务
Query OK, 0 rows affected (0.00 sec)
下面是使用rollvack;进行回滚案例
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into emp (bumen,detpId) values ('小明',1),('小红',1),('小白',2),('小绿',2);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> insert into emp (bumen,detpId) values ('小明',1),('小红',1),('小白',2),('小绿',2);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from emp;
+----+--------+--------+----------+
| id | bumen | detpId | joinDate |
+----+--------+--------+----------+
| 1 | 小明 | 1 | NULL |
| 2 | 小红 | 1 | NULL |
| 3 | 小白 | 2 | NULL |
| 4 | 小绿 | 2 | NULL |
| 17 | 小明 | 1 | NULL |
| 18 | 小红 | 1 | NULL |
| 19 | 小白 | 2 | NULL |
| 20 | 小绿 | 2 | NULL |
| 21 | 小明 | 1 | NULL |
| 22 | 小红 | 1 | NULL |
| 23 | 小白 | 2 | NULL |
| 24 | 小绿 | 2 | NULL |
+----+--------+--------+----------+
12 rows in set (0.00 sec)
####其中有错误,自行执行回滚
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from emp;
+----+--------+--------+----------+
| id | bumen | detpId | joinDate |
+----+--------+--------+----------+
| 1 | 小明 | 1 | NULL |
| 2 | 小红 | 1 | NULL |
| 3 | 小白 | 2 | NULL |
| 4 | 小绿 | 2 | NULL |
+----+--------+--------+----------+
4 rows in set (0.00 sec)
在执行两次begin,没有提交时会自动生成隔离,另一个事务回滚也不影响,而且会进行提交(即使关闭了自动提交)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into emp (bumen,detpId) values ('小明',1),('小红',1),('小白',2),('小绿',2);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> begin
-> ;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into emp (bumen,detpId) values ('小明',1),('小红',1),('小白',2),('小绿',23234);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from emp;
+----+--------+--------+----------+
| id | bumen | detpId | joinDate |
+----+--------+--------+----------+
| 1 | 小明 | 1 | NULL |
| 2 | 小红 | 1 | NULL |
| 3 | 小白 | 2 | NULL |
| 4 | 小绿 | 2 | NULL |
| 25 | 小明 | 1 | NULL |
| 26 | 小红 | 1 | NULL |
| 27 | 小白 | 2 | NULL |
| 28 | 小绿 | 2 | NULL |
+----+--------+--------+----------+
8 rows in set (0.00 sec)
关闭自动提交,有时会因为某些操作错误,但不是报错的时候,防止系统自动提交,就需要关闭自动提交
给自动提交参数赋值为0 是关闭1是开启
set autocommit=0;
mysql> select bumen as '姓名',detpId as '工资',joinDate as '领导编号' from emp;
+--------+--------+--------------+
| 姓名 | 工资 | 领导编号 |
+--------+--------+--------------+
| 小明 | 1 | NULL |
| 小红 | 1 | NULL |
| 小白 | 2 | NULL |
| 小绿 | 2 | NULL |
+--------+--------+--------------+
16 rows in set (0.00 sec)
-查询emp表中所有员工的职位
mysql> select bumen from emp;
+--------+
| bumen |
+--------+
| 小明 |
| 小红 |
| 小白 |
| 小绿 |
| 小明 |
| 小红 |
| 小白 |
| 小绿 |
+--------+
16 rows in set (0.00 sec)
mysql> select distinct bumen from emp;
去重
+--------+
| bumen |
+--------+
| 小明 |
| 小红 |
| 小白 |
| 小绿 |
+--------+
4 rows in set (0.00 sec)
mysql> select count(20000) from gong;
+--------------+
| count(20000) |
+--------------+
| 4 |
+--------------+
1 row in set (0.01 sec)
WHERE对一个表进行统计查 =
< > >= <= != (<>)
+----+--------+--------+
| id | 姓名 | 工资 |
+----+--------+--------+
| 1 | 张三 | 20000 |
| 2 | 李四 | 20000 |
| 3 | 王五 | 10000 |
| 4 | 赵六 | 2000 |
| 5 | 孙七 | 1000 |
+----+--------+--------+
查询所有工资大于2000的员工
mysql> select * from gong where 工资>=2000;
+----+--------+--------+
| id | 姓名 | 工资 |
+----+--------+--------+
| 1 | 张三 | 20000 |
| 2 | 王五 | 10000 |
| 3 | 赵六 | 2000 |
+----+--------+--------+
3 rows in set (0.00 sec)
查询所有比2000大也比2000小的
mysql> select * from gong where 工资<>2000;
+----+--------+--------+
| id | 姓名 | 工资 |
+----+--------+--------+
| 1 | 张三 | 20000 |
| 2 | 王五 | 10000 |
| 4 | 孙七 | 1000 |
+----+--------+--------+
3 rows in set (0.00 sec)
and和java中的&&一样效果,or和java中的||一样效果
between and
-在某两个数值之间包含and两边的数
select * from person where age between 22 and 28;
1.案例:查询工资2000到20000之间的姓名为
mysql> select 姓名 from gong where 工资 between 2000 and 20000;
+--------+
| 姓名 |
+--------+
| 张三 |
| 王五 |
| 赵六 |
+--------+
3 rows in set (0.00 sec)
between关键字是一个逻辑操作符用来筛选指定属性或表达式某一范围内或范围外的数据。
between关键字常用在where关键字后与select或update或delete共同使用。
2.查询工资为2000,或者为20000的员工
mysql> select 姓名 from gong where 工资=2000 or 工资=20000;
+--------+
| 姓名 |
+--------+
| 张三 |
| 赵六 |
+--------+
_ : 代表单个未知字符: 共有三个字第二个是老其它未知:_老_
% : 代表多个未知字符 .*a开头a% b结尾
%b
包含c
%c%
第二个字母是d
_d%
倒数第三个字母是e
%e__
163邮箱 %@163.com
任意com的邮箱
%@%.com
select * from user
where name like 'a%';
1.案例:查询标题包含记事本的商品
select title from t_item
where title like '%笔记本%';
2.案例:查询有赠品的DELL产品
select sell_point from t_item
where sell_point like '%赠%'
and title like '%dell%';
3.案例:查询单价低于100的记事本
select title from t_item
where price<100 and title like '%记事本%';
4.案例:查询价格介于50到200之间的得力商品
select title from t_item
where price between 50 and 200 and title like '%得力%';
5.案例:查询有图片的得力商品
select title from t_item
where image is not null
and title like '%得力%';
6.案例:查询分类为238,917的产品
select title from t_item
where category_id in (238,917);
7.案例:查询标题中不含得力的商品
select title from t_item
where title not like '%得力%';
8.案例:查询分类不是238,917的商品
select title from t_item
where category_id not in (238,917);
9.案例:查询价格介于50到200之外的商品
select title from t_item
where price not between 50 and 200;
order by排序by后面添加排序规则的字段asc :升序
select price from t_item order by price asc;省略asc/desc时,默认按升序排列
-多字段排序 会先按照第一个字段排序,如果第一个字段有数值相同的,则再通过第二个字段进行排序
需求:将表中顺序以sal升序排序
mysql> select * from person order by sal desc;
+------+-----------+------+------+--------+--------------------+
| id | name | sex | age | sal | des |
+------+-----------+------+------+--------+--------------------+
| 5 | 苍老师 | 男 | 22 | 500000 | 也是猛男一位 |
| 2 | 凤姐 | 女 | 28 | 28000 | 好吃懒惰 |
| 4 | 吕布 | 男 | 25 | 6000 | 猛男一位 |
| 1 | 貂蝉 | 女 | 68 | 5000 | 曾经漂亮 |
| 3 | 小乔 | 女 | 18 | 3000 | 美女一枚 |
| 6 | 大桥 | 女 | 19 | 1000 | 美女一枚 |
+------+-----------+------+------+--------+--------------------+
mysql> select * from person order by sal asc;
+------+-----------+------+------+--------+--------------------+
| id | name | sex | age | sal | des |
+------+-----------+------+------+--------+--------------------+
| 6 | 大桥 | 女 | 19 | 1000 | 美女一枚 |
| 3 | 小乔 | 女 | 18 | 3000 | 美女一枚 |
| 1 | 貂蝉 | 女 | 68 | 5000 | 曾经漂亮 |
| 4 | 吕布 | 男 | 25 | 6000 | 猛男一位 |
| 2 | 凤姐 | 女 | 28 | 28000 | 好吃懒惰 |
| 5 | 苍老师 | 男 | 22 | 500000 | 也是猛男一位 |
+------+-----------+------+------+--------+--------------------+
6 rows in set (0.00 sec)
mysql> select * from person order by sal asc; desc;
##mysql 查看 所有 位置 表名 开始排序 以sal 升序 降序
在大型列表中查看表内信息十分方便,如果使用select * from 表名,就会出现卡顿等等情况
mysql> select * from gong;
+----+--------+--------+
| id | 姓名 | 工资 |
+----+--------+--------+
| 1 | 张三 | 20000 |
| 2 | 王五 | 10000 |
| 3 | 赵六 | 2000 |
| 4 | 孙七 | 1000 |
+----+--------+--------+
4 rows in set (0.00 sec)
mysql> select * from gong limit 2,4; ##从2后面的值开始,向后到第四个
+----+--------+--------+
| id | 姓名 | 工资 |
+----+--------+--------+
| 3 | 赵六 | 2000 |
| 4 | 孙七 | 1000 |
+----+--------+--------+
2 rows in set (0.00 sec)
我的表不够大,只能出现小范围效果
索引的作用:能够加快用户的查询速度
本质都是:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据。
索引的数据结构
任何一种数据结构都不是凭空产生的,一定会有它的背景和使用场景,我们现在总结一下,我们需要这种数据结构能够做些什么,其实很简单,那就是:每次查找数据时把磁盘IO次数控制在一个很小的数量级,最好是常数数量级。那么我们就想到如果一个高度可控的多路搜索树是否能满足需求呢?就这样,b+树应运而生。
如上图,是一颗b+树,关于b+树的定义可以参见B+树,这里只说一些重点,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块1包含数据项17和35,包含指针P1、P2、P3,P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。真实的数据存在于叶子节点即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非叶子节点不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。
二、MySQL的索引分类
索引分类
1.普通索引index :加速查找
create index changzhang on hehe(name);
创建 索引 索引名称 指定 呵呵表(表里的name列);
drop index chengzhang on hehe; ##删除命令
删除 索引 列名 指定 表名
2.唯一索引 主键索引:primary key :加速查找+约束(不为空且唯一)
alter table hehe add primary key(id);
修改 表 表名 添加 主键(添加到id字段);
alter table hehe dorp primary key;
修改 表 表名 删除 主键
唯一索引:unique:加速查找+约束 (唯一)
alter table hehe add unique index (`age`);
修改表格式 表名 添加 唯一 索引 (`列名`); ##列名的括号里为``
drop index age on hehe; ##删除命令
删除 索引 列名 指定 表名
3.联合索引 -primary key(id,name):联合主键索引 -unique(id,name):联合唯一索引 -index(id,name):联合普通索引
create index chengzhang on hehe(id,name);
创建 索引 索引名称 指定 表名(列名,列名);
drop index chengzhang on hehe; ##删除命令
删除 索引 列名 指定 表名
4.全文索引fulltext :用于搜索很长一篇文章的时候,效果最好。 5.空间索引spatial :了解就好,几乎不用
什么是存储过程?
存储过程可以理解为之前的shell函数,里边包含多条sql语句
delimiter $$ #声明存储过程的结束符号为$$,默认为;
create procedure auto_insert1()
BEGIN
declare i int default 1; #类似于shell脚本中的i=1
while(i<3000000)do
insert into s1 values(i,concat('egon',i),'male',concat('egon',i,'@dgf'));
set i=i+1;
end while;
END$$ #$$结束
delimiter ; #重新声明分号为结束符号
create table s1(id int,name char(10),gender char(10),email char(100));###先创建表格
call auto_insert1();##引用,调用
创建完就会拥有一个内容超多的表
然后就可以
###还未添加主键时需要0.38秒
mysql> select * from s1 where id=12345;
+-------+-----------+--------+---------------+
| id | name | gender | email |
+-------+-----------+--------+---------------+
| 12345 | egon12345 | male | egon12345@dgf |
+-------+-----------+--------+---------------+
1 row in set (0.38 sec)
添加主键
mysql> alter table s1 add primary key(id);
Query OK, 0 rows affected (5.84 sec)
Records: 0 Duplicates: 0 Warnings: 0
###添加主键后只要0.00(而且我也换了id,所以不存在缓存问题)
mysql> select * from s1 where id=12333;
+-------+-----------+--------+---------------+
| id | name | gender | email |
+-------+-----------+--------+---------------+
| 12333 | egon12333 | male | egon12333@dgf |
+-------+-----------+--------+---------------+
1 row in set (0.00 sec)
是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据
视图的作用就是缓存数据,可以这么理解,我把一条sql的查询结果装在了一个视图里,我下次再查的时候,就不用走sql了,直接取这个视图里就可以了,神奇的是我可以修改这个视图里的数据,就等于修改了原表数据。
1. 视图的列可以来自不同的表,是表的抽象和逻辑意义上建立的新关系。
2. 视图是由基本表(实表)产生的表(虚表)。
3. 视图的建立和删除不影响基本表。
4. 对视图内容的更新(添加、删除和修改)直接影响基本表。
5. 当视图来自多个基本表时,不允许添加和删除数据。
视图的创建
create view 视图名称 as sql 查询语句
视图的使用
select 字段名+条件 from 视图名称;
视图的更新
update 视图名称
视图的删除
drop view 视图名称;
什么是触发器
简单的说,就是一张表发生了某件事(插入、删除、更新操作),然后自动触发了预先编写好的若干条SQL语句的执行;
触发器的作用
监视某种情况,并触发某种操作(保证数据的完整性,起到约束的作用;)
触发器创建语法四要素
1监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/before) 4.触发事件(insert/update/delete)
mysql> create trigger dgf after delete on s1 for each row
创建 触发器 名称 执行后 删除 指定 表名 就执行以下代码
-> insert into it values('架构师','段郭锋','150404199201091132','海归','10000');
###在it表中插入一行数据(前提是必须有这个表)
# 查看触发器
mysql> show triggers\G;
MySQL数据库在5.0版本后开始支持存储过程
咱在mysql中敲sql语句的时候,是一行一行的敲,那么存储过程就好比,咱把多条sql语句放到存储过程之中,然后再去执行这个存储过程
类似于函数(方法),简单的说存储过程是为了完成某个数据库中的特定功能而编写的语句集合,该语句集包括SQL语句(对数据的增删改查)、条件语句和循环语句等。
1.存储过程增强了SQL语言灵活性。
存储过程可以使用控制语句编写,可以完成复杂的判断和较复杂的运算,有很强的灵活性;
2.减少网络流量,降低了网络负载。
存储过程在服务器端创建成功后,只需要调用该存储过程即可,而传统的做法是每次都将大量的SQL语句通过网络发送至数据库服务器端然后再执行
3.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译。
一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
缺点:
1、扩展功能不方便 2、不便于系统后期维护
【实例 1】创建名称为 ShowStuScore 的存储过程,存储过程的作用是从it表中查询学生的成绩信息,输入的 SQL 语句和执行过程如下所示。
mysql> DELIMITER //
mysql> CREATE PROCEDURE ShowStuScore()
-> BEGIN
-> SELECT * FROM it;
-> END //
Query OK, 0 rows affected (0.09 sec)
DELIMITER // ##结束符改为//
mysql> CREATE PROCEDURE GetScoreByStu (IN name VARCHAR(30))
创建 带参数 名称 被引用的值
-> BEGIN
-> select 工资 from gongsi WHERE 姓名=name;
查询 查询项 指定 表明 其他项 引用值
-> END //
//结束
Query OK, 0 rows affected (0.00 sec)
mysql> CALL GetScoreByStu('张三')// ###引用张三
+--------+
| 工资 |
+--------+
| 12000 |
+--------+
mysql> DROP PROCEDURE GetScoreByStu;
删除 带参存储 名称
create database test;
########创建表
CREATE TABLE `user` (
`id` int(4) NOT NULL,
`sex` enum('f','m') DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
########创建另一个表
CREATE TABLE `userinfo` (
`sn` int(4) NOT NULL AUTO_INCREMENT,
`userid` int(4) NOT NULL,
`info` varchar(20) DEFAULT NULL,
PRIMARY KEY (`sn`),
KEY `userid` (`userid`),
CONSTRAINT `userinfo_ibfk_1` FOREIGN KEY (`userid`) REFERENCES `user` (`id`) ON DELETE
创建外键约束 名称 将 userid 于 user表的id这一列做外键约束
CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
###插入数据:
INSERT INTO `user` (`id`,`sex`)
VALUES ('1', 'f'), ('2', 'm'), ('3', 'f');
mysql> select * from user;
+----+------+
| id | sex |
+----+------+
| 1 | f |
| 2 | m |
| 3 | f |
+----+------+
3 rows in set (0.00 sec)
###在另一个表中也插入数据:
INSERT INTO `userinfo` (`sn`,`userid`,`info`)
VALUES ('1', '1', '2005054dsf'),
('2', '1', 'fdsfewfdsfds'),
('3', '1', 'gdsgergergrtre'),
('4', '2', 'et34t5435435werwe'),
('5', '2', '435rtgtrhfghfg'),
('6', '2', 'ret345tr4345'),
('7', '3', 'fgbdfvbcbfdgr'),
('8', '3', '45r2343234were'),
('9', '3', 'wfyhtyjtyjyjy');
mysql> select * from userinfo;
+----+--------+-------------------+
| sn | userid | info |
+----+--------+-------------------+
| 1 | 1 | 2005054dsf |
| 2 | 1 | fdsfewfdsfds |
| 3 | 1 | gdsgergergrtre |
| 4 | 2 | et34t5435435werwe |
| 5 | 2 | 435rtgtrhfghfg |
| 6 | 2 | ret345tr4345 |
| 7 | 3 | fgbdfvbcbfdgr |
| 8 | 3 | 45r2343234were |
| 9 | 3 | wfyhtyjtyjyjy |
+----+--------+-------------------+
9 rows in set (0.00 sec)
delete from `user` where `id`='2';
mysql> select * from user;
+----+------+
| id | sex |
+----+------+
| 1 | f |
| 3 | f |
+----+------+
2 rows in set (0.00 sec)
mysql> select * from userinfo;
+----+--------+----------------+
| sn | userid | info |
+----+--------+----------------+
| 1 | 1 | 2005054dsf |
| 2 | 1 | fdsfewfdsfds |
| 3 | 1 | gdsgergergrtre |
| 7 | 3 | fgbdfvbcbfdgr |
| 8 | 3 | 45r2343234were |
| 9 | 3 | wfyhtyjtyjyjy |
+----+--------+----------------+
6 rows in set (0.00 sec)
对比一下发现两张表里的id为2的全部没了
可以得出结论,外键约束就是将两张表绑定起来,然后对一张表做出操作,另一张表重复同样的操作
ALTER TABLE user DROP FOREIGN KEY userinfo_ibfk_1;
修改 表格 表名 删除 外键约束 外键名称;
mysql> create table money(id int,name varchar(20),age int);
insert into money values(1,"刘备",45),(2,"关羽",43),(3,"张飞",43);
mysql> select * from money;
+------+--------+------+
| id | name | age |
+------+--------+------+
| 1 | 刘备 | 45 |
| 2 | 关羽 | 43 |
| 3 | 张飞 | 43 |
+------+--------+------+
3 rows in set (0.00 sec)
###第二个表
mysql> create table bingqi(id int,bingqi varchar(60));
insert into bingqi values(1,"双股剑"),(2,"青龙偃月刀"),(3,"丈八蛇矛");
mysql> select * from bingqi;
+------+-----------------+
| id | bingqi |
+------+-----------------+
| 1 | 双股剑 |
| 2 | 青龙偃月刀 |
| 3 | 丈八蛇矛 |
+------+-----------------+
3 rows in set (0.00 sec)
mysql> select name,bingqi from money,bingqi WHERE money.id=bingqi.id;
+--------+-----------------+
| name | bingqi |
+--------+-----------------+
| 刘备 | 双股剑 |
| 关羽 | 青龙偃月刀 |
| 张飞 | 丈八蛇矛 |
+--------+-----------------+
3 rows in set (0.00 sec)
mysql> select name,bingqi from money,bingqi where money.id=1 and bingqi.id=1;
+--------+-----------+
| name | bingqi |
+--------+-----------+
| 刘备 | 双股剑 |
+--------+-----------+
1 row in set (0.00 sec)
mysql> insert into money values(4,"吕布",30);
mysql> select name,bingqi from money m left outer join bingqi b on m.id=b.id;
+--------+-----------------+
| name | bingqi |
+--------+-----------------+
| 刘备 | 双股剑 |
| 关羽 | 青龙偃月刀 |
| 张飞 | 丈八蛇矛 |
| 吕布 | NULL |
+--------+-----------------+
4 rows in set (0.00 sec)
mysql> select name,bingqi from money m right outer join bingqi b on m.id=b.id;
+--------+-----------------+
| name | bingqi |
+--------+-----------------+
| 刘备 | 双股剑 |
| 关羽 | 青龙偃月刀 |
| 张飞 | 丈八蛇矛 |
+--------+-----------------+
3 rows in set (0.00 sec)
总结:从上边的输出可以看出来,左外链接以左表为主,右外链接以右表为主
表锁就是把整张表锁起来,特点是加锁快,开销小,不会出现死锁,锁粒度大,发生锁冲突的概率高,并发相对较低。
行锁就是以行为单位把数据锁起来,特点是加锁慢,开销大,会出现死锁,锁粒度小,发生锁冲突的概率低,并发度也相对表锁较高。
死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环。
添加读锁:
LOCK TABLES tb_name READ; 加读锁,可读,但不能更新,如果写入会陷入一直加载中。
LOCK TABLES tb_name WRITE; 加写锁,其他会话不可读,不可写。
UNLOCK TABLES; 释放锁
一个事务获取了一个数据行的读锁,允许其他事务也来获取读锁,但是不允许其他事务来获取写锁。也就是说,我上了读锁之后,其他事务也可以来读,但是不能增删改。