您的位置:首页 > 数据库 > MySQL

第八章| 3. MyAQL数据库|Navicat工具与pymysql模块 | 内置功能 | 索引原理

2018-05-02 10:28 441 查看

1、Navicat工具与pymysql模块

在生产环境中操作MySQL数据库还是推荐使用命令行工具mysql,但在我们自己开发测试时,可以使用可视化工具Navicat,以图形界面的形式操作MySQL数据库
[/code]
掌握:
#1. 测试+链接数据库
#2. 新建库
#3. 新建表,新增字段+类型+约束
#4. 设计表:外键
#5. 新建查询
#6. 备份库/表

#注意:
批量加注释:ctrl+?键
批量去注释:ctrl+shift+?键

之前我们都是通过MySQL自带的命令行客户端工具mysql来操作数据库,那如何在python程序中操作数据库呢?这就用到了pymysql模块,该模块本质就是一个套接字客户端软件,使用前需要事先安装   

pip3 install pymysql

准备账号、表

用cmd授权一个账号

C:\Users\Administrator>mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 5.6.39 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> grant all on *.* to 'root'@'%' identified by '123';
Query OK, 0 rows affected (0.07 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.12 sec)

查看IP地址:

在管理员权限下运行cmd,输入ipconfig 

IPv4 地址 . . . . . . . . . . . . : 192.168.1.123

import pymysql

user=input('user>>: ').strip()
pwd=input('password>>: ').strip()

# 建立链接
conn=pymysql.connect(
host='192.168.1.123',
port=3306,
user='root',
password='123',
db='db10',
charset='utf8'
)

# 拿到游标
cursor=conn.cursor()

# 执行sql语句
# sql='select * from userinfo where user = "%s" and pwd="%s"' %(user,pwd)
# print(sql)

sql='select * from userinfo where user = %s and pwd=%s'
rows=cursor.execute(sql,(user,pwd)) #提交给游标执行  execute这个接口拿到的是2 rows in set (0.00 sec) 2那个行数,如果值不为0说明就输对了

cursor.close()
conn.close()

# 进行判断
if rows:
print('登录成功')
else:
print('登录失败')

 

mysql语句中 -- xfjl ,--+空格后边的都给你注释掉了

import pymysql

user=input('user>>: ').strip()
pwd=input('password>>: ').strip()

# 建立链接
conn=pymysql.connect(
host='192.168.1.123',
port=3306,
user='root',
password='123',
db='db10',
charset='utf8'
)

# 拿到游标
cursor=conn.cursor()

# 执行sql语句
sql='select * from userinfo where user = "%s" and pwd="%s"' %(user,pwd)
print(sql)
rows=cursor.execute(sql)

#sql='select * from userinfo where user = %s and pwd=%s'
#由execute作为拼接,不用你自己去拼接了,在拼接过程中给你过滤掉这种非法操作
#rows=cursor.execute(sql,(user,pwd)) #提交给游标执行  execute这个接口拿到的是2 rows in set (0.00 sec) 2那个行数,如果值不为0说明就输对了

cursor.close()
conn.close()

# 进行判断
if rows:
print('登录成功')
else:
print('登录失败')

打印: #两种执行的错误
user>>: egon" -- xxxhhhh
password>>:
select * from userinfo where user = "egon" -- xxxhhhh" and pwd=""
登录成功

user>>: xxxx" or 1=1 -- hhhhhaaa
password>>:
select * from userinfo where user = "xxxx" or 1=1 -- hhhhhaaa" and pwd=""
登录成功

改正:

import pymysql

user=input('user>>: ').strip()
pwd=input('password>>: ').strip()

# 建立链接
conn=pymysql.connect(
host='192.168.1.123',
port=3306,
user='root',
password='123',
db='db10',
charset='utf8'
)

# 拿到游标
cursor=conn.cursor()

# 执行sql语句
# sql='select * from userinfo where user = "%s" and pwd="%s"' %(user,pwd)
# print(sql)
# rows=cursor.execute(sql)

sql='select * from userinfo where user = %s and pwd=%s'
#由execute作为拼接,不用你自己去拼接了,在拼接过程中给你过滤掉这种非法操作
rows=cursor.execute(sql,(user,pwd)) #提交给游标执行  execute这个接口拿到的是2 rows in set (0.00 sec) 2那个行数,如果值不为0说明就输对了

cursor.close()
conn.close()

# 进行判断
if rows:
print('登录成功')
else:
print('登录失败')

增加

import pymysql

# 建立链接
conn=pymysql.connect(
host='192.168.1.123',
port=3306,
user='root',
password='123',
db='db10',
charset='utf8'
)

# 拿游标
cursor=conn.cursor()

# 执行sql
# 增、删、改  对数据的变动
sql='insert into userinfo(user,pwd) values(%s,%s)'
rows=cursor.execute(sql,('wxx','123'))
print(rows)

conn.commit() #必须加上这个
# 关闭
cursor.close()
conn.close()

打印:
1
#1、增删改
import pymysql

# 建立链接
conn=pymysql.connect(
host='192.168.1.123',
port=3306,
user='root',
password='123',
db='db10',
charset='utf8'
)

# 拿游标
cursor=conn.cursor()

# 执行sql
# 增、删、改  对数据的变动
sql='insert into userinfo(user,pwd) values(%s,%s)'
# rows=cursor.execute(sql,('wxx','123'))
# print(rows)
rows=cursor.executemany(sql,[('yxx','123'),('egon1','111'),('egon2','2222')]) #可以插入多条
print(rows)

conn.commit() #必须加上这个
# 关闭
cursor.close()
conn.close()

打印
3

 

 

#2、查询
import pymysql
# # 建立链接
conn=pymysql.connect(
host='192.168.1.123',
port=3306,
user='root',
password='123',
db='db10',
charset='utf8'
)

# 拿游标
cursor=conn.cursor(pymysql.cursors.DictCursor) #基于字典形式的游标,不加括号内的是以元组形式

# 执行sql
# 查询
rows=cursor.execute('select * from userinfo;') #把字符串send给服务端,在服务端把这个sql语句执行下,然后把结果丢给客户端
print(rows)
# print(cursor.fetchone()) #代表取一行
# print(cursor.fetchone())
# print(cursor.fetchone())
# print(cursor.fetchone())
# print(cursor.fetchone())
# print(cursor.fetchone())
# print(cursor.fetchone())

#print(cursor.fetchmany(2)) #指定取的个数,以列表的形式

#print(cursor.fetchall()) #拿出所有,列表的形式
# print(cursor.fetchall())

cursor.scroll(3,mode='absolute') #移动光标 相对绝对位置移动,从头数3个开始取出来1个,结果是第4个
#print(cursor.fetchone())
cursor.scroll(2,mode='relative') # 相对当前位置移动 往后跳2位
print(cursor.fetchone())
# 关闭
cursor.close()
conn.close()

打印:
6
{'id': 6, 'user': 'egon2', 'pwd': '2222'}

 

import pymysql
#
# # 建立链接
conn=pymysql.connect(
host='192.168.1.123',
port=3306,
user='root',
password='123',
db='db10',
charset='utf8'
)
#
# # 拿游标
cursor=conn.cursor()

sql='insert into userinfo(user,pwd) values(%s,%s)'

rows=cursor.executemany(sql,[('egon3','123'),('egon4','111'),('egon5','2222')])
print(cursor.lastrowid) #插入之前光标走到哪里了
#
conn.commit() #必须加上这个
# 关闭
cursor.close()
conn.close()

打印:
7

涉及数据库的操作的,先要编写好数据,然后基于pymysql模块帮我把sql语句提交给mysql服户端,执行完之后把结果再返回到应用程序中再做进一步的处理;将应用程序的开发与数据库的开发结合

2、mysql内置函数功能

  视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】,用户使用时只需使用【名称】即可获取结果集,可以将该结果集当做表来使用。

  使用视图我们可以把查询过程中的临时表摘出来,用视图去实现,这样以后再想操作该临时表的数据时就无需重写复杂的sql了,直接去视图中查找即可,但视图有明显地效率问题,并且视图是存放在数据库中的,如果我们程序中使用的sql过分依赖数据库中的视图,即强耦合,那就意味着扩展sql极为不便,因此并不推荐使用

  视图 只有表结构frm,没有数据,因为是查出来的虚拟表;不用重复写,但是不建议使用,如果有好多个视图,要找到所有的视图给它修改很麻烦;

mysql> use db7;
Database changed
mysql> select * from course;
+-----+--------+------------+
| cid | cname  | teacher_id |
+-----+--------+------------+
|   1 | 生物   |          1 |
|   2 | 物理   |          2 |
|   3 | 体育   |          3 |
|   4 | 美术   |          2 |
+-----+--------+------------+
4 rows in set (0.00 sec)

mysql> select * from teacher;
+-----+-----------------+
| tid | tname           |
+-----+-----------------+
|   1 | 张磊老师        |
|   2 | 李平老师        |
|   3 | 刘海燕老师      |
|   4 | 朱云海老师      |
|   5 | alex            |
+-----+-----------------+
5 rows in set (0.00 sec)

mysql> select * from course inner join teacher on course.teacher_id=teacher.tid;
+-----+--------+------------+-----+-----------------+
| cid | cname  | teacher_id | tid | tname           |
+-----+--------+------------+-----+-----------------+
|   1 | 生物   |          1 |   1 | 张磊老师        |
|   2 | 物理   |          2 |   2 | 李平老师        |
|   4 | 美术   |          2 |   2 | 李平老师        |
|   3 | 体育   |          3 |   3 | 刘海燕老师      |
+-----+--------+------------+-----+-----------------+
4 rows in set (0.10 sec)

mysql> create view course2teacher as select * from course inner join teacher on course.teacher_id=teacher.tid;
Query OK, 0 rows affected (0.20 sec)

mysql> show tables;
+----------------+
| Tables_in_db7  |
+----------------+
| course         |
| course2teacher |
| teacher        |
+----------------+
3 rows in set (0.00 sec)

mysql>

 

触发器

使用触发器可以定制用户对表进行【增、删、改】操作时前后的行为,注意:没有查询

mysql> create database db11;
Query OK, 1 row affected (0.00 sec)

mysql> use db11;
Database changed
mysql> CREATE TABLE cmd (
->     id INT PRIMARY KEY auto_increment,
->     USER CHAR (32),
->     priv CHAR (10),
->     cmd CHAR (64),
->     sub_time datetime, #提交时间
->     success enum ('yes', 'no') #0代表执行失败
-> );
Query OK, 0 rows affected (0.77 sec)

mysql>
mysql> CREATE TABLE errlog (
->     id INT PRIMARY KEY auto_increment,
->     err_cmd CHAR (64),
->     err_time datetime
-> );
Query OK, 0 rows affected (0.68 sec)

#创建触发器 mysql> delimiter // mysql> CREATE TRIGGER tri_after_insert_cmd AFTER INSERT ON cmd FOR EACH ROW -> BEGIN -> IF NEW.success = 'no' THEN #等值判断只有一个等号 -> INSERT INTO errlog(err_cmd, err_time) VALUES(NEW.cmd, NEW.sub_time) ; #必须加分号 -> END IF ; #必须加分号 -> END// Query OK, 0 rows affected (0.34 sec) mysql> delimiter ; mysql> mysql> mysql>#往cmd中插入记录,触动触发器,根据IF条件决定是否插入错误日志 mysql> INSERT INTO cmd ( -> USER, -> priv, -> cmd, -> sub_time, -> success -> ) -> VALUES -> ('egon','0755','ls -l /etc',NOW(),'yes'), -> ('egon','0755','cat /etc/passwd',NOW(),'no'), -> ('egon','0755','useradd xxx',NOW(),'no'), -> ('egon','0755','ps aux',NOW(),'yes'); Query OK, 4 rows affected (0.43 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> select * from cmd; +----+------+------+-----------------+---------------------+---------+ | id | USER | priv | cmd | sub_time | success | +----+------+------+-----------------+---------------------+---------+ | 1 | egon | 0755 | ls -l /etc | 2018-04-28 18:26:33 | yes | | 2 | egon | 0755 | cat /etc/passwd | 2018-04-28 18:26:33 | no | | 3 | egon | 0755 | useradd xxx | 2018-04-28 18:26:33 | no | | 4 | egon | 0755 | ps aux | 2018-04-28 18:26:33 | yes | +----+------+------+-----------------+---------------------+---------+ 4 rows in set (0.00 sec) mysql> select * from errlog; #查询错误日志发现有两条 +----+-----------------+---------------------+ | id | err_cmd | err_time | +----+-----------------+---------------------+ | 1 | cat /etc/passwd | 2018-04-28 18:26:33 | | 2 | useradd xxx | 2018-04-28 18:26:33 | +----+-----------------+---------------------+ 2 rows in set (0.00 sec)

存储过程

把mysql处理好的数据给封装好,一个接口名,应用程序可以直接调用接口,这个接口就叫储存过程。是mysql内置功能的一系列总和;

存储过程包含了一系列可执行的sql语句,存储过程存放于MySQL中,通过调用它的名字可以执行其内部的一堆sql

使用存储过程的优点:

1. 用于替代程序写的SQL语句,实现程序与sql解耦

2. 基于网络传输,传别名的数据量小,而直接传sql数据量大

使用存储过程的缺点:

1. 程序员扩展功能不方便

程序与数据库结合使用的三种方式:

#方式一:
MySQL:存储过程
程序:调用存储过程
#方式二:
MySQL:
程序:纯SQL语句
#方式三:
MySQL:
程序:类和对象,即ORM(本质还是纯SQL语句)

创建简单的存储过程:

#1、无参存储过程
delimiter //
create procedure p1()
BEGIN
select * from db7.teacher;
END //
delimiter ;
mysql> use db7;
Database changed
mysql> delimiter //
mysql> create procedure p1()
-> BEGIN
-> select * from db7.teacher;
-> END //
Query OK, 0 rows affected (0.21 sec)

mysql> delimiter ;
mysql>
mysql>
mysql> show create procedure p1;
+-----------+--------------------------------------------+-----------------------------------------------------------------------------------------+----------------------+----------------------+------
--------------+
| Procedure | sql_mode                                   | Create Procedure                                                                        | character_set_client | collation_connection | Datab
ase Collation |
+-----------+--------------------------------------------+-----------------------------------------------------------------------------------------+----------------------+----------------------+------
--------------+
| p1        | STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION | CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
BEGIN
select * from db7.teacher;
END | utf8                 | utf8_general_ci      | utf8_general_ci    |
+-----------+--------------------------------------------+-----------------------------------------------------------------------------------------+----------------------+----------------------+------
--------------+
1 row in set (0.00 sec)
# MySQL中调用
call p1();
mysql> call p1();
+-----+-----------------+
| tid | tname           |
+-----+-----------------+
|   1 | 张磊老师        |
|   2 | 李平老师        |
|   3 | 刘海燕老师      |
|   4 | 朱云海老师      |
|   5 | alex            |
+-----+-----------------+
5 rows in set (0.00 sec)

Query OK, 0 rows affected (0.01 sec)
# Python中调用
cursor.callproc('p1') #调用存储过程
import pymysql

# 建立链接
conn=pymysql.connect(
host='192.168.1.123',
port=3306,
user='root',
password='123',
db='db7',
charset='utf8'
)

# 拿游标
cursor=conn.cursor()

# 执行sql
cursor.callproc('p1') #只是执行
print(cursor.fetchall())

打印
((1, '张磊老师'), (2, '李平老师'), (3, '刘海燕老师'), (4, '朱云海老师'), (5, 'alex'))

#2、有参存储过程   #在mysql中参数必须指定类型,是用来接收值的还是返回值的
对于存储过程,可以接收参数,其参数有三类:
#in          仅用于传入参数用
#out        仅用于返回值用
#inout     既可以传入又可以当作返回值
delimiter //
create procedure p2(in n1 int,in n2 int,out res int) #当存储过程p1执行完了,就把res当做返回值返回了这就是out的作用,只有out的值才能被返回
BEGIN
select * from db7.teacher where tid > n1 and tid < n2;
set res = 1;
END //
delimiter ;

# MySQL中调用
set @x=0 #初始值等于零
call p2(2,4,@x);
select @x;查看结果

# Python中调用
cursor.callproc('p2',(2,4,0))# @_p2_0=2,@_p2_1=4,@_p2_2=0
cursor.execute('select @_p3_2')
cursor.fetchone()
mysql> delimiter //
mysql> create procedure p2(in n1 int, in n2 int, out res int)
-> BEGIN
-> select * from db7.teacher where tid > n1 and tid < n2;
-> set res = 1;
-> END //
Query OK, 0 rows affected (0.06 sec)

mysql> delimiter ;

mysql> set @x=0;
Query OK, 0 rows affected (0.00 sec)

mysql> call p2(2,4,@x);
+-----+-----------------+
| tid | tname           |
+-----+-----------------+
|   3 | 刘海燕老师      |
+-----+-----------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> select @x;
+------+
| @x   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
import pymysql

# 建立链接
conn=pymysql.connect(
host='192.168.1.123',
port=3306,
user='root',
password='123',
db='db7',
charset='utf8'
)

# 拿游标
cursor=conn.cursor()

#
cursor.execute('select @_p2_2')
print(cursor.fetchone())

# 关闭
cursor.close()
conn.close()

打印
(1, )

应用程序与数据库结合使用
方式一: (很少用,部门之间沟通效率不高;优点很好解开了耦合,效率最高)
Python:调用存储过程
MySQL:编写存储过程

方式二:
Python:编写纯生SQL  (可维护性好,都是开发人员写的,)
MySQL:

方式三:
Python:ORM->纯生SQL (开发效率高,可维护性高,用类,ORM框架)
MySQL:

事务

同时成功同时失败;

 事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。

mysql> create table user(
-> id int primary key auto_increment,
-> name char(32),
-> balance int
-> );
Query OK, 0 rows affected (1.98 sec)

mysql>
mysql> insert into user(name,balance)
-> values
-> ('wsb',1000),
-> ('egon',1000),
-> ('ysb',1000);
Query OK, 3 rows affected (0.50 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from user;
+----+------+---------+
| id | name | balance |
+----+------+---------+
|  1 | wsb  |    1000 |
|  2 | egon |    1000 |
|  3 | ysb  |    1000 |
+----+------+---------+
3 rows in set (0.00 sec)

#原子操作 mysql> start transaction; Query OK, 0 rows affected (0.05 sec) mysql> update user set balance=900 where name='wsb'; #买支付100元 Query OK, 1 row affected (0.11 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update user set balance=1010 where name='egon'; #中介拿走10元 Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update user set balance=1090 where name='ysb'; #卖家拿到90元 Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from user; +----+------+---------+ | id | name | balance | +----+------+---------+ | 1 | wsb | 900 | | 2 | egon | 1010 | | 3 | ysb | 1090 | +----+------+---------+ 3 rows in set (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.16 sec) mysql> select * from user; +----+------+---------+ | id | name | balance | +----+------+---------+ | 1 | wsb | 900 | | 2 | egon | 1010 | | 3 | ysb | 1090 | +----+------+---------+ 3 rows in set (0.00 sec) mysql> rollback; #出现异常就回滚到初始状态 Query OK, 0 rows affected (0.00 sec) mysql> select * from user; +----+------+---------+ | id | name | balance | +----+------+---------+ | 1 | wsb | 900 | | 2 | egon | 1010 | | 3 | ysb | 1090 | +----+------+---------+ 3 rows in set (0.00 sec)

函数与流程控制

函数

一、数学函数
ROUND(x,y)
返回参数x的四舍五入的有y位小数的值

RAND()
返回0到1内的随机值,可以通过提供一个参数(种子)使RAND()随机数生成器生成一个指定的值。

二、聚合函数(常用于GROUP BY从句的SELECT查询中)
AVG(col)返回指定列的平均值
COUNT(col)返回指定列中非NULL值的个数
MIN(col)返回指定列的最小值
MAX(col)返回指定列的最大值
SUM(col)返回指定列的所有值之和
GROUP_CONCAT(col) 返回由属于一组的列值连接组合而成的结果

三、字符串函数

CHAR_LENGTH(str)
返回值为字符串str 的长度,长度的单位为字符。一个多字节字符算作一个单字符。
CONCAT(str1,str2,...)
字符串拼接
如有任何一个参数为NULL ,则返回值为 NULL。
CONCAT_WS(separator,str1,str2,...)
字符串拼接(自定义连接符)
CONCAT_WS()不会忽略任何空字符串。 (然而会忽略所有的 NULL)。

CONV(N,from_base,to_base)
进制转换
例如:
SELECT CONV('a',16,2); 表示将 a 由16进制转换为2进制字符串表示

FORMAT(X,D)
将数字X 的格式写为'#,###,###.##',以四舍五入的方式保留小数点后 D 位, 并将结果以字符串的形式返回。若  D 为 0, 则返回结果不带有小数点,或不含小数部分。
例如:
SELECT FORMAT(12332.1,4); 结果为: '12,332.1000'
INSERT(str,pos,len,newstr)
在str的指定位置插入字符串
pos:要替换位置其实位置
len:替换的长度
newstr:新字符串
特别的:
如果pos超过原字符串长度,则返回原字符串
如果len超过原字符串长度,则由新字符串完全替换
INSTR(str,substr)
返回字符串 str 中子字符串的第一个出现位置。

LEFT(str,len)
返回字符串str 从开始的len位置的子序列字符。

LOWER(str)
变小写

UPPER(str)
变大写

REVERSE(str)
返回字符串 str ,顺序和字符顺序相反。

SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)
不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos。 使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。假若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在以下格式的函数中可以对pos 使用一个负值。

mysql> SELECT SUBSTRING('Quadratically',5);
-> 'ratically'

mysql> SELECT SUBSTRING('foobarbar' FROM 4);
-> 'barbar'

mysql> SELECT SUBSTRING('Quadratically',5,6);
-> 'ratica'

mysql> SELECT SUBSTRING('Sakila', -3);
-> 'ila'

mysql> SELECT SUBSTRING('Sakila', -5, 3);
-> 'aki'

mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2);
-> 'ki'

四、日期和时间函数
CURDATE()或CURRENT_DATE() 返回当前的日期
CURTIME()或CURRENT_TIME() 返回当前的时间
DAYOFWEEK(date)   返回date所代表的一星期中的第几天(1~7)
DAYOFMONTH(date)  返回date是一个月的第几天(1~31)
DAYOFYEAR(date)   返回date是一年的第几天(1~366)
DAYNAME(date)   返回date的星期名,如:SELECT DAYNAME(CURRENT_DATE);
FROM_UNIXTIME(ts,fmt)  根据指定的fmt格式,格式化UNIX时间戳ts
HOUR(time)   返回time的小时值(0~23)
MINUTE(time)   返回time的分钟值(0~59)
MONTH(date)   返回date的月份值(1~12)
MONTHNAME(date)   返回date的月份名,如:SELECT MONTHNAME(CURRENT_DATE);
NOW()    返回当前的日期和时间
QUARTER(date)   返回date在一年中的季度(1~4),如SELECT QUARTER(CURRENT_DATE);
WEEK(date)   返回日期date为一年中第几周(0~53)
YEAR(date)   返回日期date的年份(1000~9999)

重点:
DATE_FORMAT(date,format) 根据format字符串格式化date值

mysql> SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y');
-> 'Sunday October 2009'
mysql> SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s');
-> '22:23:00'
mysql> SELECT DATE_FORMAT('1900-10-04 22:23:00',
->                 '%D %y %a %d %m %b %j');
-> '4th 00 Thu 04 10 Oct 277'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
->                 '%H %k %I %r %T %S %w');
-> '22 22 10 10:23:00 PM 22:23:00 00 6'
mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V');
-> '1998 52'
mysql> SELECT DATE_FORMAT('2006-06-00', '%d');
-> '00'

五、加密函数
MD5()
计算字符串str的MD5校验和
PASSWORD(str)
返回字符串str的加密版本,这个加密过程是不可逆转的,和UNIX密码加密过程使用不同的算法。

六、控制流函数
CASE WHEN[test1] THEN [result1]...ELSE [default] END
如果testN是真,则返回resultN,否则返回default
CASE [test] WHEN[val1] THEN [result]...ELSE [default]END
如果test和valN相等,则返回resultN,否则返回default

IF(test,t,f)
如果test是真,返回t;否则返回f

IFNULL(arg1,arg2)
如果arg1不是空,返回arg1,否则返回arg2

NULLIF(arg1,arg2)
如果arg1=arg2返回NULL;否则返回arg1

 

mysql> CREATE TABLE blog (
->     id INT PRIMARY KEY auto_increment,
->     NAME CHAR (32),
->     sub_time datetime
-> );
Query OK, 0 rows affected (0.78 sec)

mysql> INSERT INTO blog (NAME, sub_time)
-> VALUES
->     ('第1篇','2015-03-01 11:31:21'),
->     ('第2篇','2015-03-11 16:31:21'),
->     ('第3篇','2016-07-01 10:21:31'),
->     ('第4篇','2016-07-22 09:23:21'),
->     ('第5篇','2016-07-23 10:11:11'),
->     ('第6篇','2016-07-25 11:21:31'),
->     ('第7篇','2017-03-01 15:33:21'),
->     ('第8篇','2017-03-01 17:32:21'),
->     ('第9篇','2017-03-01 18:31:21');
Query OK, 9 rows affected (0.14 sec)
Records: 9  Duplicates: 0  Warnings: 0

mysql> SELECT DATE_FORMAT(sub_time,'%Y-%m'),COUNT(1) FROM blog GROUP BY DATE_FORMAT(sub_time,'%Y-%m');
+-------------------------------+----------+
| DATE_FORMAT(sub_time,'%Y-%m') | COUNT(1) |
+-------------------------------+----------+
| 2015-03                       |        2 |
| 2016-07                       |        4 |
| 2017-03                       |        3 |
+-------------------------------+----------+
3 rows in set (0.22 sec)

mysql>

流程控制

delimiter //
CREATE PROCEDURE proc_if ()
BEGIN

declare i int default 0;
if i = 1 THEN
SELECT 1;
ELSEIF i = 2 THEN
SELECT 2;
ELSE
SELECT 7;
END IF;

END //
delimiter ;

if条件语句

 

3、索引原理

索引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构。

索引相当于字典的音序表,如果要查某个字,如果不使用音序表,则需要从几百页中逐页去查。

若索引太多,应用程序的性能可能会受到影响。而索引太少,对查询性能又会产生影响,要找到一个平衡点,这对应用程序的性能至关重要。

索引的目的在于提高查询效率,与我们查阅图书所用的目录是一个道理:先定位到章,然后定位到该章下的一个小节,然后找到页数。相似的例子还有:查字典,查火车车次,飞机航班等

本质都是:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据。

数据库复杂的多,因为不仅面临着等值查询,还有范围查询(>、<、between、in)、模糊查询(like)、并集查询(or)等等。数据库应该选择怎么样的方式来应对所有的问题呢?我们回想字典的例子,能不能把数据分成段,然后分段查询呢?最简单的如果1000条数据,1到100分成第一段,101到200分成第二段,201到300分成第三段......这样查第250条数据,只要找第三段就可以了,一下子去除了90%的无效数据。但如果是1千万的记录呢,分成几段比较好?稍有算法基础的同学会想到搜索树,其平均复杂度是lgN,具有不错的查询性能。但这里我们忽略了一个关键的问题,复杂度模型是基于每次相同的操作成本来考虑的。而数据库实现比较复杂,一方面数据是保存在磁盘上的,另外一方面为了提高性能,每次又可以把部分数据读入内存来计算,因为我们知道访问磁盘的成本大概是访问内存的十万倍左右,所以简单的搜索树难以满足复杂的应用场景。

  当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。每一次IO读取的数据我们称之为一页(page)。

  每次查找数据时把磁盘IO次数控制在一个很小的数量级,最好是常数数量级。那么我们就想到如果一个高度可控的多路搜索树是否能满足需求呢?就这样,b+树应运而生(B+树是通过二叉查找树,再由平衡二叉树,B树演化而来)。

 

b+树性质 1.索引字段要尽量的小;2.索引的最左匹配特性

这种数据结构减少I/O次数

真实数据只存在叶子节点的磁盘块的数据项;树杈节点的数据象就是为了建数据结构而虚拟出的;

I/O固定在固定范围,3次,它的高度决定的。

InnoDB存储引擎表示索引组织表,即表中数据按照主键顺序存放,建表的时候一定要建个主键,它会在你这个表里边找主键;

聚集索引与辅助索引

数据库中的B+树索引可以分为聚集索引(clustered index)和辅助索引(secondary index),

聚集索引与辅助索引相同的是:不管是聚集索引还是辅助索引,其内部都是B+树的形式,即高度是平衡的,叶子结点存放着所有的数据。

聚集索引与辅助索引不同的是:叶子结点存放的是否是一整行的信息

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: