1 数据库的介绍?

之前, 我们存取数据的时候, 使用的是Excel表格来进行管理, 但是, 随着数据量的增多,使用Excel表格就不行了, 而且我么还有一些高级的查询,需要工具软件来帮助我们取完成, 这个软件就是数据库软件

数据库就是一个帮助我们进行数据管理的软件(工具)

2 数据库的分类

    a. 关系型数据库
            1. 有约束
            2. 基于硬盘存储的

            具体实现的软件:
                MySQL(免费),SQLServer(微软 c# .net), Oracle(甲骨文, java), SQLlite, DB2 
                mariadb, pgsql

    b. 非关系型数据库
            1. 没有约束   {“key”--->value, "key"---> "bdshabd"}
            2. 基于内存存储的

            具体实现的软件:
                Memcache(03), redis(10年 微博), mongodb

3 安装MySQL数据库

a. 架构

    MySQL服务端:
        socketserver服务端
        接收来自客户端的指令, 执行, 然后将结果返回

    MySQL客户端:
        socket client客户端
        发送指令到服务端

b. 安装:

http://dev.mysql.com/downloads/mysql/

1.zip:
    压缩包 (MySQL的客户端和服务端已经开发好, 然后打包给你)

2.exe文件或者msi文件:
    点点点 (下一步)

3.目录结构:
    bin : 
        MySQLd : 启动MySQL服务端的
        MySQL  : 连接服务端
    data: 
        存放数据文件

4.具体的安装:
    mac:
        brew install mysql    

    windows:
        a.解压
        b.进入到bin
        c.mysqld  (默认一个用户名root)
        d.mysql -uroot -p 直接回车 再回车
        e:mysql>输入指令

    环境变量:
        右键计算机】--》【属性】--》【高级系统设置】--》【高级】--》【环境变量】--》
        【在第二个内容框中找到 变量名为Path 的一行,双击】 --> 添加

上面是解决了一些问题,但不够彻底,因为在执行【mysqd】启动MySQL服务器时,当前终端会被hang住,那么做一下设置即可解决此问题:

# 制作MySQL的Windows服务,在终端执行此命令:
"c:\mysql-5.7.16-winx64\bin\mysqld" --install

# 移除MySQL的Windows服务,在终端执行此命令:
"c:\mysql-5.7.16-winx64\bin\mysqld" --remove
注册成服务之后,以后再启动和关闭MySQL服务时,仅需执行如下命令:


# 启动MySQL服务
net start mysql

# 关闭MySQL服务
net stop mysql

4. mysql的操作:

操作文件夹(数据库):
操作文件(数据表):
数据行(具体的一行数据)

4.1 数据库增删改

增
语句:
    create database 数据库名;
例子:
    create database db1;

删
    drop database (数据库名)db2;

改
    删掉数据库, 然后新建

查:
    列出当前数据库下面的所有数据库:show databases;

使用数据库:
    use 数据库名(db2);

4.2 数据表

4.2.1 mysql数据类型

1.数值型

补充:

  • unsigned 表示为无符号
  • float(M,D)浮点型
  • decimal(M,D)定点型比float更加的精准
  • M:精度(总位数)D:标度(小数位)

2.字符串类型

3.时间日期类型

4.特殊的NULL类型

  • NULL 不是假,也不是真,而是”空”
  • NULL 的判断只能用is null,is not null
  • NULL 影响查询速度,一般避免使值为NUL

4.2.2 数据表增删改查

指令:
create table 表名(
    列名, 列属性,
    列名, 列属性,
    列名, 列属性,
    列名, 列属性,
);

语句:

版本0:
create table t1(
    id  int,
    name char(32)
);
语句:
insert into 表名 (列名1,列名2,...., 列n )values(值1,值2,...值n);
例子:
insert into t1 (id, name)values(1, 'zekai');
insert into t1 (id, name)values(1, '你好');
版本1:
create table t2(
    id  int,
    name char(32)
)charset=utf8;

insert into t2 (id, name)values(1, 'zekai');
insert into t2 (id, name)values(1, '你好');
版本2:
create table t3(
    id  int auto_increment primary key,
    name char(32)
)charset=utf8;

insert into t3 (name, age)values('zekai', 12);
insert into t3 (name)values('eagon');
insert into t3 (name)values('xxxx');
版本3:
create table t3(
    id  int auto_increment primary key,
    name char(32) not null default ''
)engine=Innodb charset=utf8;

auto_increment: 自增 要和primary key 一起使用
null : 默认是是nullnot null : 不能为null
default : 指定默认值

最后一列语句不能加逗号

ps:
存储引擎:
    MyIsam (5.5以下)  和 Innodb(5.5以上)

最终建表的语句格式:(********************)

create table 表名 (
    列1 列属性 [是否为null 默认值],
    列2 列属性 [是否为null 默认值],
    .....
    列n 列属性 [是否为null 默认值]
)engine = 存储引擎  charset = 字符集

例子:
create table t4(
    id  int auto_increment primary key,
    id  unsigned int auto_increment primary key,
    name char(32) not null default '',
    create_time datetime not null default '1970-01-01 00:00:00'
)engine=Innodb charset=utf8;

查看建表语句:
    show create table 表名(t3);  ====> 建表过程显示

查看表中列的详细信息:
    desc 表名(t3);

查看数据:
    select * from 表名(t1);

    drop table 表名; (表里的数据都会没有)

修改表中的列:
    修改一列:
        alter table 表名(t3) change  老列名(name)   新列名(usernme char(32));
    添加一列:
        alter table 表名(t3) add  新列名(age int); 
    删除一列;
        alter table 表名(t3) drop 老列名(age);

4.3 数据行增删改查

指令:
    insert into 表名(列1,列2,...., 列n) values (‘值1’, '值2', ..., '值n');
实例:

#添加一行数据:
    insert into t3 (name, age)values('zekai', 12);

#添加多行数据:
    insert into t3 (username, age)values('zekai', 12), ('eagon', 78), ('lxxx', 83);
    #将别的表中的数据添加到表中:
        insert into t4 (name, age) select usernme,  age from t3;

指令:    
    delete from 表名(t2);  ### 再次插入数据的时候, id是从上一次主键id开始的
    truncate t4;  ### 删除数据, 然后再次插入数据的时候, id从1开始
    delete from t2 where id=10;

指令:
    update 表名 set name='xxxx';
语句:
    update t4 set name='kkkk',age=12,gender='女' where id=2;
    update t4 set name='kkkk' where id>2;
    update t4 set name='kkkk' where id<2;
    update t4 set name='kkkk' where id<=2;
    update t4 set name='kkkk' where id>=2;
    update t4 set name='kkkk' where id!=2;

指令:
    select * from t3; ### 将所有的列的值全部显示
    select 列名1, 列名2.... from t3;

where条件:
select * from t3 where id=12;
select * from t3 where id>12;
select * from t3 where id>=12;
select * from t3 where id<12;
select * from t3 where id<=12;
select * from t3 where id!=12;

select * from t4 where id > 13 and id < 30; 

select * from t4 where id > 13 or name='mmmm'; 

between ... and : 在某一个范围之内(闭区间)

    select * from t4 where id between 13 and 30;
inselect * from t4 where id in (16,20,30);
not in:
    select * from t4 where id not in (16,20,30);

通配符匹配:

select * from t4 where name like 'j%';  %: 匹配字符串后面所有的字符
select * from t4 where name like 'j_';  _:  只匹配一个字符

限制取几条:

select * from t4 limit 索引偏移量,取多少条

select * from t4 limit 0, 10;

page      索引偏移量      取多少条(offset)   
  1          0               10
  2          10              10
  3          20              10
  ......


分页的SQL语句:(****************)
page = input('please input page num:')
offset = 20

select * from t4 limit (page-1)*offset, offset;

排序:

从大到小 : 降序

从小到大 : 升序

order by 列名 desc/asc

select * from t4 order by age desc, id asc; ### 首先按照age进行降序,

分组:

group by 列名

聚合函数:

count(): 计数
sum()  : 求和
max()  : 最大值
min()  : 最小值
avg()  : 平均值



例子:
    select age, count(age) from t4 group by age;
    select age, sum(age) from t4 group by age;

having:

select age, count(id) as cnt from t4 group by age having cnt>=2;
对分组完之后的结果进行二次删选

和where条件的区别;
where 对表中原生的列进行删选
having 对分组之后的结果进行二次删选

5 外键

5.1 唯一索引

create table yyy(
    id int,
    num int,
    unique u_name (num) ,
    unique u_id_name (id, num)  ### 联合唯一索引   1,1   1,2
)engine=Innodb charset=utf8;

5.2 一对多

缺点:
    1. 重复太厉害
    2. 如果部门名称过长的话, 重复去写的话, 占用空间太厉害

方法:
    通过新建一张表来解决
create table department(
    id int auto_increment primary key, 
    name varchar(32) not null default ''
)engine=Innodb charset=utf8;

insert into department (name) values ('公关部'), ('前台部'), ('保安部'), ('xxxx');
create table userinfo(
    id int auto_increment primary key, 
    name varchar(32) not null default '',
    age int not null default 1,
    depart_id int, 
    constraint fk_userinfo_depart foreign key(depart_id) references department(id),
    constraint fk_userinfo_depart foreign key(depart_id) references department(id),
    constraint fk_userinfo_depart foreign key(depart_id) references department(id),
    constraint fk_userinfo_depart foreign key(depart_id) references department(id),
)engine=Innodb charset=utf8;

insert into userinfo (name, age, depart_id) values ('zzzz', 12, 3);    
insert into userinfo (name, age, depart_id) values ('kkkk', 23, 1);    
insert into userinfo (name, age, depart_id) values ('hhhh', 45, 2);    
insert into userinfo (name, age, depart_id) values ('bbbb', 56, 3);    

insert into userinfo (name, age, depart_id) values ('zzzz', 12, 32);

ps:

1. 主键名称不能重复
2. 可一建多个外键,方法一样, 但是建立的外键一定是另一张表中的主键

5.3 一对一

userinfo

    id   name     age 
    1     eagon   23     
    2     zekai   23     
    3     lxxx    23   
    4     linhaifeng   78

blog表:                   外键 + 唯一约束
    id     url             uid
    1      /linhaifeng/     4
    2      /lxxx/           3

5.4 多对多

userinfo            
    id    name    age    
    1    root1    23    
    2    root2    24    
    3    root3    25    
    4    root4    26    
    5    root5    27    

host    
    id    name
    1    c1.com
    2    c2.com
    3    c3.com

user2host            
    id    uid    hid    
    1    1    1    
    2    1    2    
    3    1    3    
    4    2    1    
    5    2    3    
  1. 一个用户下面有多少台主机?
    目前:
    给userinfo表加一个字段 host_id

  2. 一台主机下面有多少个用户?

6 连表查询:

select * from userinfo,department where department.id=userinfo.depart_id;

left join:

    select * from userinfo left join department on department.id=userinfo.depart_id;
    左边表数据全部显示


right join:
    select * from userinfo right join department on department.id=userinfo.depart_id;
    右边的数据全部显示

inner join:
    select * from userinfo inner join department on department.id=userinfo.depart_id;
    不显示有空行的数据

7 SQL嵌套子查询

不建议大家在线上使用SQL子查询进行操作

建议: 将SQL语句分叉成多条简单的SQL语句, 分别查询, 速度是快于嵌套查询

公司:每周五 代码的review

内容:

1. 函数类 变量的命名风格

    大驼峰法 (def GetUserInfo
    小驼峰法  (def getUserInfo
    下划线    (def get_user_info)

    def getUserInfo

    user_info

2. 函数的函数体不能超过30行  (高内聚低耦合)

3. 变量名和等号之间 要加空格

4. SQL语句是否有嵌套

8 pymysql

安装: pip3 install pymysql

create table userinfo (
    id int auto_increment primary key,
    name varchar(32) not null default '',
    email varchar(32) not null default ''
)engine=Innodb charset=utf8;

pymysql操作数据库:

1. conn = pymysql.conn 链接数据库
2. cursor = con.cursor()
3. cursor.execute(sql语句)
查询
    4. cursor.fetchone() # 取一行数据
    5. cursor.fetchmany(5) ## 取指定的数据
    6. cursor.fetchall() #  取到所有的结果集

增加

    增加一条数据:
        cursor.execute(insert 语句, 传入的参数)

    增加多条数据:
        cursor.executemany(insert 语句, 传入的多个参数)

    conn.commit()                

删除
    删除一条数据:
        cursor.execute(delete语句, 传入的参数)

    删除多条数据:
        cursor.executemany(delete语句, 传入的多个参数)
    conn.commit()

修改
    删除一条数据:
        cursor.execute(update语句, 传入的参数)

    删除多条数据:
        cursor.executemany(update语句,传入的多个参数)

    conn.commit()

安全问题:

sql注入:
    攻击代码:
        1. zekai' #
            select * from user where name = 'zekai' #' and pwd = ''

        2. bdshabdhsa' or 1=1 #
            select * from user where name = 'bdshabdhsa' or 1=1 #' and pwd = ''

    产生的原因:

        太相信用户传入的值 (默认用户都是君子)

    如何防护:
        过滤用户输入的值

    python中的做法:
        sql = "select * from user where name = %s and pwd = %s"

        cursor.execute(sql, (username, pwd))

csrf攻击
xss攻击

python连接数据库

import pymysql

db = pymysql.connect("数据库ip","用户","密码","数据库" ) # 打开数据库连接
cursor.execute("SELECT VERSION()")                    # 使用 execute() 方法执行 SQL 查询
data = cursor.fetchone()                              # 使用 fetchone() 方法获取单条数据
print ("Database version : %s " % data)
db.close()                                            # 关闭数据库连接
# 更多参数
import pymysql

conn = pymysql.connect(
        host='localhost', user='root', password="root",
        database='db', port=3306, charset='utf-8',
)

cur = conn.cursor(cursor=pymysql.cursors.DictCursor)

创建表操作

import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )

# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()

# 使用 execute() 方法执行 SQL,如果表存在则删除
cursor.execute("DROP TABLE IF EXISTS EMPLOYEE")

# 使用预处理语句创建表
sql = """CREATE TABLE EMPLOYEE (
         FIRST_NAME  CHAR(20) NOT NULL,
         LAST_NAME  CHAR(20),
         AGE INT,  
         SEX CHAR(1),
         INCOME FLOAT )"""

cursor.execute(sql)

# 关闭数据库连接
db.close()

操作数据

插入操作

import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )

# 使用cursor()方法获取操作游标 
cursor = db.cursor()

# SQL 插入语句
sql = """INSERT INTO EMPLOYEE(FIRST_NAME,
         LAST_NAME, AGE, SEX, INCOME)
         VALUES ('Mac', 'Mohan', 20, 'M', 2000)"""
try:
   cursor.execute(sql) # 执行sql语句
   db.commit()         # 提交到数据库执行
except:
   db.rollback()       # 如果发生错误则回滚

# 关闭数据库连接
db.close()
# 另一种形式

import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )

# 使用cursor()方法获取操作游标 
cursor = db.cursor()

# SQL 插入语句
sql = "INSERT INTO EMPLOYEE(FIRST_NAME, \
       LAST_NAME, AGE, SEX, INCOME) \
       VALUES (%s, %s,  %s,  %s,  %s )" % \
       ('Mac', 'Mohan', 20, 'M', 2000)
try:

   cursor.execute(sql)  # 执行sql语句
   db.commit()          # 执行sql语句
except:
   db.rollback()        # 发生错误时回滚

# 关闭数据库连接
db.close()

查询操作

Python查询Mysql使用 fetchone() 方法获取单条数据, 使用fetchall() 方法获取多条数据。

  • fetchone(): 该方法获取下一个查询结果集。结果集是一个对象
  • fetchall(): 接收全部的返回结果行.
  • rowcount: 这是一个只读属性,并返回执行execute()方法后影响的行数。
import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )

# 使用cursor()方法获取操作游标 
cursor = db.cursor()

# SQL 查询语句
sql = "SELECT * FROM EMPLOYEE \
       WHERE INCOME > %s" % (1000)
try:

   cursor.execute(sql)# 执行SQL语句
   results = cursor.fetchall()# 获取所有记录列表
   for row in results:
      fname = row[0]
      lname = row[1]
      age = row[2]
      sex = row[3]
      income = row[4]
       # 打印结果
      print ("fname=%s,lname=%s,age=%s,sex=%s,income=%s" % \
             (fname, lname, age, sex, income ))
except:
   print ("Error: unable to fetch data")

# 关闭数据库连接
db.close()

更新操作

import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )

# 使用cursor()方法获取操作游标 
cursor = db.cursor()

# SQL 更新语句
sql = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = '%c'" % ('M')
try:
   cursor.execute(sql)  # 执行SQL语句
   db.commit()          # 提交到数据库执行
except
   db.rollback()        # 发生错误时回滚

# 关闭数据库连接
db.close()

删除操作

import pymysql

# 打开数据库连接
db = pymysql.connect("localhost","testuser","test123","TESTDB" )

# 使用cursor()方法获取操作游标 
cursor = db.cursor()

# SQL 删除语句
sql = "DELETE FROM EMPLOYEE WHERE AGE > %s" % (20)
try
   cursor.execute(sql)  # 执行SQL语句
   db.commit()          # 提交修改
except
   db.rollback()        # 发生错误时回滚# 关闭连接
db.close()

9 索引

作用: 
    加速查找

类似: 
    新华字典的索引目录   如果没有这个索引目录, 我们查询的时候需要从前到后进行遍历查询
    特殊的二进制文件, 就可以通过此文件定位到想要的值

原理:
    B+ 树

索引的类型

主键索引: 加速查找 + 不能为空 + 不能重复 primary key

    create table xxx(
        id int ,

        name varchar(32) not null default '',
        unique uq_name (name)
    )

    alter tbale xxx change id  id int primary key;

唯一索引: 加速查找 + 不能重复 unique(name)

    联合唯一索引: 加速查找 + 两列不能重复
    create table xxx(
        id int auto_increment primary key,

        name varchar(32) not null default '',
        unique uq_name (name)
    )

        create unique  ix_name on xxx (name)

普通索引: 加速查找 index ix_name(name)
组合索引: 加速查找 index ix_name_email (name, email)

创建的两种方式:

        create table xxx(
            id int auto_increment primary key,

            name varchar(32) not null default '',

            index ix_name (name)
        )

        create index ix_name on xxx (name)

查看索引:

show indexes from xxxx;

删除索引:

对普通索引, 唯一索引:
    drop index 索引名 on 表名;
对主键索引:
    alter table 表名 drop primary key;

是否需要对每一列都要加索引?

不是的
原因:
    索引固然加速了查找, 但是对增加, 删除, 修改, 效率是不高的

加索引的原则:

    根据业务决定(向经常使用的字段上加索引)

索引使用的条件:

加了索引并不能一定用到
根据具体的SQL语句判断是否用的索引

索引不适用的情况:

不要适用 like
不要在语句中适用函数

mysql性能分析之explain

Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的索引和优化查询语句,写出更好的优化语句。

Explain语法:explain select … from … [where …]

例如:explain select * from news;

输出:

+--+-----------+-----+----+-------------+---+-------+---+----+-----+
|id|select_type|table|type|possible_keys|key|key_len|ref|rows|Extra|
+--+-----------+-----+----+-------------+---+-------+---+----+-----+

下面对各个属性进行了解:

1、id:这是SELECT的查询序列号

2、select_type:select_type就是select的类型,可以有以下几种:

SIMPLE:简单SELECT(不使用UNION或子查询等)

PRIMARY:最外面的SELECT

UNIONUNION中的第二个或后面的SELECT语句

DEPENDENT UNIONUNION中的第二个或后面的SELECT语句,取决于外面的查询

UNION RESULTUNION的结果。

SUBQUERY:子查询中的第一个SELECT

DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询

DERIVED:导出表的SELECT(FROM子句的子查询)

3、table:显示这一行的数据是关于哪张表的

4、type:这列最重要,显示了连接使用了哪种类别,有无使用索引,是使用Explain命令分析性能瓶颈的关键项之一。

结果值从好到坏依次是:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题。

5、possible_keys:列指出MySQL能使用哪个索引在该表中找到行

6、key:显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL

7、key_len:显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。使用的索引的长度。在不损失精确性的情况下,长度越短越好

8、ref:显示使用哪个列或常数与key一起从表中选择行。

9、rows:显示MySQL认为它执行查询时必须检查的行数。

10、Extra:包含MySQL解决查询的详细信息,也是关键参考项之一。

Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了

Not exists
MYSQL 优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,

就不再搜索了

Range checked for each

Record(index map:#)
没有找到理想的索引,因此对于从前面表中来的每一 个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一

Using filesort
看 到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来 排序全部行

Using index
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表 的全部的请求列都是同一个索引的部分的时候

Using temporary
看到这个的时候,查询需要优化了。这 里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上

Using where
使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index, 这就会发生,或者是查询有问题

其他一些Tip:

  • 当type 显示为 “index” 时,并且Extra显示为“Using Index”, 表明使用了覆盖索引。

10 慢日志:

slow_query_log = OFF                       是否开启慢日志记录
long_query_time = 2                        时间限制,超过此时间,则记录
slow_query_log_file = /usr/slow.log        日志文件

普通日志:

general log

11 事务

create table users (
    id int auto_increment primary key,
    name varchar(32) not null default '',
    money int not null default 0
)engine=Innodb charset=utf8;


insert into users (name, money) values ('zekai', 1000),('lxxx', 500);

一组操作:

update users set money=900 where id=1; (执行成功)
update users set money=600 where id=2; (执行失败)

概念:

  • 一组操作, 要么全都成功, 要么全都失败

用法:

  • 开启事务(start transaction)
  • 执行sql操作(普通sql操作)
  • 提交/回滚(commit/rollback)

特性:

  • 原子性(Atomicity),原子意为最小的粒子,即不能再分的事务,要么全部执行,要么全部取消(就像上面的银行例子)
  • 一致性(Consistency):指事务发生前和发生后,数据的总额依然匹配
  • 隔离性(Isolation):简单点说,某个事务的操作对其他事务不可见的
  • 持久性(Durability):当事务完成后,其影响应该保留下来,不能撤消,只能通过“补偿性事务”来抵消之前的错误

事务支持引擎:
Innodb 和 MyISam 区别:

  • Innodb支持事务, myISam不支持
  • 版本5.5 默认Innodb 版本5.5一下 默认MyISam
  • Innodb支持行锁 (并发量大使用) MyISam表锁
begin;  # 开启事务
select * from emp where id = 1 for update;  # 查询id值,for update添加行锁;
update emp set salary=10000 where id = 1; # 完成更新
commit; # 提交事务

12 数据备份恢复

数据库的逻辑备份

#语法:
# mysqldump -h 服务器 -u用户名 -p密码 数据库名 > 备份文件.sql

#示例:
#单库备份
mysqldump -uroot -p123 db1 > db1.sql
mysqldump -uroot -p123 db1 table1 table2 > db1-table1-table2.sql

#多库备份
mysqldump -uroot -p123 --databases db1 db2 mysql db3 > db1_db2_mysql_db3.sql

#备份所有库
mysqldump -uroot -p123 --all-databases > all.sql

数据恢复

#方法一:
[root@egon backup]# mysql -uroot -p123 < /backup/all.sql

#方法二:
mysql> use db1;
mysql> SET SQL_LOG_BIN=0;   #关闭二进制日志,只对当前session生效
mysql> source /root/db1.sql

13 MySQL创建及删除临时表

示例SQL:

drop temporary table if exists testdb.tmp_test_table;
create temporary table testdb.tmp_test_table ( id integer, name varchar(20) );
insert into testdb.tmp_test_table values (1, 'zifeiy'), (2, 'balala');
drop temporary table testdb.tmp_test_table;

注意:关闭对话框后临时表自动删除

14 MySQL case when 用法

MySQL 的 case when 的语法有两种:

简单函数
CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END
搜索函数
CASE WHEN [expr] THEN [result1]…ELSE [default] END
这两种语法有什么区别呢?

简单函数

CASE [col_name] WHEN [value1] THEN [result1]…ELSE [default] END: 枚举这个字段所有可能的值*

SELECT
    NAME '英雄',
    CASE NAME
        WHEN '德莱文' THEN
            '斧子'
        WHEN '德玛西亚-盖伦' THEN
            '大宝剑'
        WHEN '暗夜猎手-VN' THEN
            '弩'
        ELSE
            '无'
    END '装备'
FROM
    user_info;
SELECT
    NAME '英雄',
    CASE NAME
        WHEN '德莱文' THEN
            '斧子'
        WHEN '德玛西亚-盖伦' THEN
            '大宝剑'
        WHEN '暗夜猎手-VN' THEN
            '弩'
        ELSE
            '无'
    END '装备'
FROM
    user_info;

搜索函数

CASE WHEN [expr] THEN [result1]…ELSE [default] END:搜索函数可以写判断,并且搜索函数只会返回第一个符合条件的值,其他case被忽略

# when 表达式中可以使用 and 连接条件
SELECT
    NAME '英雄',
    age '年龄',
    CASE
        WHEN age < 18 THEN
            '少年'
        WHEN age < 30 THEN
            '青年'
        WHEN age >= 30
        AND age < 50 THEN
            '中年'
        ELSE
            '老年'
    END '状态'
FROM
    user_info;

聚合函数 sum 配合 case when 的简单函数实现行转列
SELECT
    st.stu_id '学号',
    st.stu_name '姓名',
    sum(
        CASE co.course_name
        WHEN '大学语文' THEN
            sc.scores
        ELSE
        END
    ) '大学语文',
    sum(
        CASE co.course_name
        WHEN '新视野英语' THEN
            sc.scores
        ELSE
        END
    ) '新视野英语',
    sum(
        CASE co.course_name
        WHEN '离散数学' THEN
            sc.scores
        ELSE
        END
    ) '离散数学',
    sum(
        CASE co.course_name
        WHEN '概率论与数理统计' THEN
            sc.scores
        ELSE
        END
    ) '概率论与数理统计',
    sum(
        CASE co.course_name
        WHEN '线性代数' THEN
            sc.scores
        ELSE
        END
    ) '线性代数',
    sum(
        CASE co.course_name
        WHEN '高等数学' THEN
            sc.scores
        ELSE
        END
    ) '高等数学'
FROM
    edu_student st
LEFT JOIN edu_score sc ON st.stu_id = sc.stu_id
LEFT JOIN edu_courses co ON co.course_no = sc.course_no
GROUP BY
    st.stu_id
ORDER BY
    NULL;

行转列测试数据

-- 创建表  学生表
CREATE TABLE `edu_student` (
    `stu_id` VARCHAR (16) NOT NULL COMMENT '学号',
    `stu_name` VARCHAR (20) NOT NULL COMMENT '学生姓名',
    PRIMARY KEY (`stu_id`)
) COMMENT = '学生表' ENGINE = INNODB;

-- 课程表 
CREATE TABLE `edu_courses` (
    `course_no` VARCHAR (20) NOT NULL COMMENT '课程编号',
    `course_name` VARCHAR (100) NOT NULL COMMENT '课程名称',
    PRIMARY KEY (`course_no`)
) COMMENT = '课程表' ENGINE = INNODB;

-- 成绩表
CREATE TABLE `edu_score` (
    `stu_id` VARCHAR (16) NOT NULL COMMENT '学号',
    `course_no` VARCHAR (20) NOT NULL COMMENT '课程编号',
    `scores` FLOAT NULL DEFAULT NULL COMMENT '得分',
    PRIMARY KEY (`stu_id`, `course_no`)
) COMMENT = '成绩表' ENGINE = INNODB;

-- 插入数据

-- 学生表数据

INSERT INTO edu_student (stu_id, stu_name)
VALUES
    ('1001', '盲僧'),
    ('1002', '赵信'),
    ('1003', '皇子'),
    ('1004', '寒冰'),
    ('1005', '蛮王'),
    ('1006', '狐狸');

-- 课程表数据 
INSERT INTO edu_courses (course_no, course_name)
VALUES
    ('C001', '大学语文'),
    ('C002', '新视野英语'),
    ('C003', '离散数学'),
    (
        'C004',
        '概率论与数理统计'
    ),
    ('C005', '线性代数'),
    ('C006', '高等数学');

-- 成绩表数据
INSERT INTO edu_score (stu_id, course_no, scores)
VALUES
    ('1001', 'C001', 67),   ('1002', 'C001', 68),   ('1003', 'C001', 69),   ('1004', 'C001', 70),   ('1005', 'C001', 71),
    ('1006', 'C001', 72),   ('1001', 'C002', 87),   ('1002', 'C002', 88),   ('1003', 'C002', 89),   ('1004', 'C002', 90),
    ('1005', 'C002', 91),   ('1006', 'C002', 92),   ('1001', 'C003', 83),   ('1002', 'C003', 84),   ('1003', 'C003', 85),
    ('1004', 'C003', 86),   ('1005', 'C003', 87),   ('1006', 'C003', 88),   ('1001', 'C004', 88),   ('1002', 'C004', 89),
    ('1003', 'C004', 90),   ('1004', 'C004', 91),   ('1005', 'C004', 92),   ('1006', 'C004', 93),   ('1001', 'C005', 77),
    ('1002', 'C005', 78),   ('1003', 'C005', 79);

企业案例:

SELECT MONTH
    ( send_date ) AS 月份,
    deliver_cityid AS 城市,
CASE

    WHEN bill_card_money > 0 THEN
    "现金卡" 
    WHEN bill_card_money = 0 THEN
    "散客" 
    END AS 类型,
    count( 1 ) AS 订单量 
FROM
    bill_master 
WHERE
    send_date >= '2019-01-01' 
    AND send_date < '2019-07-01' 
    AND bill_status = 7 
GROUP BY
    1,
    2,
3;

15 MySQL对时间的处理总结

1、to_days函数查询今天的数据:select * from 表名 where to_days(时间字段名) = to_days(now());
to_days函数:返回从0000年(公元1年)至当前日期的总天数

2、DAYOFWEEK(date) ,返回日期date的星期索引(1=星期天,2=星期一, ……7=星期六)。这些索引值对应于ODBC标准。

3、WEEKDAY(date) ,返回date的星期索引(0=星期一,1=星期二, ……6= 星期天)。

4、DAYOFMONTH(date) ,返回date的月份中日期,在1到31范围内。

5、DAYOFYEAR(date) ,返回date在一年中的日数, 在1到366范围内

6、MONTH(date) ,返回date的月份,范围1到12。

7、DAYNAME(date) ,返回date的星期名字。

8、MONTHNAME(date) ,返回date的月份名字。

9、QUARTER(date) ,返回date一年中的季度,范围1到4。


select TO_DAYS(NOW()) - TO_DAYS('2017-11-02');//1

select DAYOFWEEK('2017-11-05'); //1(注意周日是1)

select WEEKDAY('2017-11-03');//4(0开始)

select DAYOFMONTH('2017-11-03');//3

select dayofyear('2017-11-03')//307

select month('2017-11-03')//11

select dayname('2017-11-03')//Friday

select MONTHNAME('2017-11-03')//November

select QUARTER('2017-11-03')//4

10、WEEK(date):对于星期天是一周的第一天的地方,有一个单个参数,返回date的周数,范围在0到52。

  WEEK(date,first) :2个参数形式WEEK()允许你指定星期是否开始于星期天或星期一。如果第二个参数是0,星期从星期天开始,如果第二个参数是1, 从星期一开始。

11、YEAR(date) ,返回date的年份,范围在1000到9999。

12、HOUR(time) ,返回time的小时,范围是0到23。

13、MINUTE(time) ,返回time的分钟,范围是0到59。

14、SECOND(time) ,回来time的秒数,范围是0到59。

select WEEK('2017-11-05'); //45(周日开始算一周,11.05是周日,算新的一周)
select WEEK('2017-11-05',1);//44(周一开始算一周,11.05是周日,还不算新的一周)

select YEAR('2017-11-03');//2017

select HOUR('2017-11-03 11:05:36')//11

select MINUTE('2017-11-03 11:05:36')//5

select SECOND('2017-11-03 11:05:36')//36

15、PERIOD_ADD(P,N) ,增加N个月到阶段P(以格式YYMM或YYYYMM)。以格式YYYYMM返回值。注意阶段参数P不是日期值。

16、PERIOD_DIFF(P1,P2) ,返回在时期P1和P2之间月数,P1和P2应该以格式YYMM或YYYYMM。注意,时期参数P1和P2不是日期值。

select PERIOD_ADD('201711',2); //201801

select PERIOD_DIFF('201711','201702');//9

17、计算:

    DATE_ADD(date,INTERVAL expr type)   
  DATE_SUB(date,INTERVAL expr type)   
  ADDDATE(date,INTERVAL expr type)  
  SUBDATE(date,INTERVAL expr type)  

  这些功能执行日期运算。对于MySQL 3.22,他们是新的。ADDDATE()和SUBDATE()是DATE_ADD()和DATE_SUB()的同义词。在MySQL 3.23中,你可以使用+和-而不是DATE_ADD()和DATE_SUB()。(见例子)

  date:是一个指定开始日期的DATETIME或DATE值;

  expr:是指定加到开始日期或从开始日期减去的间隔值一个表达式。expr是一个字符串,它可以以一个“-”开始表示负间隔。

  type:是一个关键词,指明表达式应该如何被解释。

下表显示了type和expr参数怎样被关联: type值 含义 期望的expr格式  
SECOND 秒 SECONDS
MINUTE 分钟 MINUTES
HOUR 时间 HOURS
DAY 天 DAYS
MONTH 月 MONTHS
YEAR 年 YEARS
MINUTE_SECOND 分钟和秒 "MINUTES:SECONDS"
HOUR_MINUTE 小时和分钟 "HOURS:MINUTES"
DAY_HOUR 天和小时 "DAYS HOURS"
YEAR_MONTH 年和月 "YEARS-MONTHS"
HOUR_SECOND 小时, 分钟, "HOURS:MINUTES:SECONDS"
DAY_MINUTE 天, 小时, 分钟 "DAYS HOURS:MINUTES"
DAY_SECOND 天, 小时, 分钟, 秒 "DAYS HOURS:MINUTES:SECONDS"

  MySQL在expr格式中允许任何标点分隔符,表示显示的是建议的分隔符。如果date参数是一个DATE值并且你的计算仅仅包含YEAR、MONTH和DAY部分(即,没有时间部分),结果是一个DATE值。否则结果是一个DATETIME值。

SELECT "2017-11-05 23:59:59" + INTERVAL 1 SECOND; //2017-11-06 00:00:00

select INTERVAL 2 day + "2017-11-05" //2017-11-07

select "2017-11-05" - INTERVAL 2 SECOND //2017-11-04 23:59:58

SELECT DATE_ADD("2017-11-05 23:59:59",INTERVAL 1 SECOND); //2017-11-06 00:00:00

SELECT DATE_ADD("2017-11-05 23:59:59",INTERVAL 1 DAY); //2017-11-06 23:59:59

SELECT DATE_ADD("2017-11-05 23:59:59",INTERVAL "1:1" MINUTE_SECOND);//2017-11-06 00:01:00

SELECT DATE_SUB("2017-11-05 23:59:59",INTERVAL "1:1" MINUTE_SECOND);//2017-11-05 23:58:58

SELECT DATE_ADD("2017-11-05 23:59:59",INTERVAL "-1 10" DAY_HOUR);//2017-11-04 13:59:59

SELECT DATE_SUB("2017-11-05 23:59:59",INTERVAL 31 DAY);//2017-10-05 23:59:59
SELECT DATE_SUB("2017-11-05 23:59:59",INTERVAL -31 DAY);//2017-12-06 23:59:59

注意:如果你增加MONTH、YEAR_MONTH或YEAR并且结果日期大于新月份的最大值天数,日子在新月用最大的天调整。

select DATE_ADD('2017-01-30', Interval 1 month); //2017-02-28

18、EXTRACT(type FROM date),函数从日期中返回“type”间隔。

SELECT EXTRACT(YEAR FROM "2017-11-05");//2017
SELECT EXTRACT(YEAR_MONTH FROM "2017-11-05");//201711
SELECT EXTRACT(DAY_MINUTE FROM "2017-11-05 01:02:03");//50102
SELECT EXTRACT(DAY_MINUTE FROM "2017-11-15 01:02:03");//15102

19、FROM_DAYS(N) ,给出一个天数N,返回一个DATE值。

select FROM_DAYS(729669);//1997-10-07

20、DATE_FORMAT(date,format) ,根据format字符串格式化date值。

//下列修饰符可以被用在format字符串中: 
%M 月名字(January……December)  
%W 星期名字(Sunday……Saturday)  
%D 有英语前缀的月份的日期(1st, 2nd, 3rd, 等等。)  
%Y 年, 数字, 4 位  
%y 年, 数字, 2 位  
%a 缩写的星期名字(Sun……Sat)  
%d 月份中的天数, 数字(00……31)  
%e 月份中的天数, 数字(0……31)  
%m 月, 数字(01……12)  
%c 月, 数字(1……12)  
%b 缩写的月份名字(Jan……Dec)  
%j 一年中的天数(001……366)  
%H 小时(00……23)  
%k 小时(0……23)  
%h 小时(01……12)
%I 小时(01……12)
%l 小时(1……12)
%i 分钟, 数字(00……59)  
%r 时间,12 小时(hh:mm:ss [AP]M)  
%T 时间,24 小时(hh:mm:ss)  
%S 秒(00……59)  
%s 秒(00……59)  
%p AM或PM  
%w 一个星期中的天数(0=Sunday ……6=Saturday )  
%U 星期(0……52), 这里星期天是星期的第一天  
%u 星期(0……52), 这里星期一是星期的第一天  
%% 一个文字“%”。  

//所有的其他字符不做解释被复制到结果中。
mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');  
-> 'Saturday October 1997'  
mysql> select DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');  
-> '22:23:00'  
mysql> select DATE_FORMAT('1997-10-04 22:23:00',  
'%D %y %a %d %m %b %j');  
-> '4th 97 Sat 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'  
//MySQL3.23中,在格式修饰符字符前需要%。在MySQL更早的版本中,%是可选的。

21、TIME_FORMAT(time,format) ,这象上面的DATE_FORMAT()函数一样使用,但是format字符串只能包含处理小时、分钟和秒的那些格式修饰符。 其他修饰符产生一个NULL值或0。

22、CURDATE()或CURRENT_DATE,以’YYYY-MM-DD’或YYYYMMDD格式返回今天日期值,取决于函数是在一个字符串还是数字上下文被使用。

23、CURTIME()或CURRENT_TIME,以’HH:MM:SS’或HHMMSS格式返回当前时间值,取决于函数是在一个字符串还是在数字的上下文被使用。

24、NOW()、SYSDATE()、CURRENT_TIMESTAMP,以’YYYY-MM-DD HH:MM:SS’或YYYYMMDDHHMMSS格式返回当前的日期和时间,取决于函数是在一个字符串还是在数字的上下文被使用。

25、SEC_TO_TIME(seconds),返回seconds参数,变换成小时、分钟和秒,值以’HH:MM:SS’或HHMMSS格式化,取决于函数是在一个字符串还是在数字上下文中被使用。

26、TIME_TO_SEC(time),返回time参数,转换成秒。

select CURDATE();  //2017-11-03
select CURDATE() + 0;  //20171103

select curtime();  //17:36:12
select curtime() + 0;  //173612

select NOW();//2017-11-03 17:38:07
select NOW() + 0;//20171103173825

select SEC_TO_TIME(2378);//00:39:38

select TIME_TO_SEC("22:23:00");//80580

16 mysql拼接字符串

  1. 准备表
    create table ct(
    id int(10) PRIMARY KEY,
    name varchar(20) UNIQUE ,
    age int(3)
    )

1.1 准备数据

insert into ct (id,name,age)
values    (1,"小明1",21),
        (2,"小明2",null),
        (3,"小明3",23),
        (4,"小明4",24);
  1. concat(str,str,str…)
    直接拼接,如果其中一个为空,返回结果当前列为空
mysql>  select concat(id,`name`,age) from ct ;  
+-----------------------+
| concat(id,`name`,age) |
+-----------------------+
| 1小明121              |
| NULL                  |
| 3小明323              |
| 4小明424              |
+-----------------------+
4 rows in set (0.00 sec)
  1. concat_ws(separator,str,str,str…)
    代表 concat with separator ,是concat()的特殊形式。第一个参数是其它参数的分隔符。分隔符的位置放在要连接的两个字符串之间。分隔符可以是一个字符串,也可以是其它参数。
mysql>  select concat_ws("-",id,`name`,age) from ct ; 
+------------------------------+
| concat_ws("-",id,`name`,age) |
+------------------------------+
| 1-小明1-21                   |
| 2-小明2                      |
| 3-小明3-23                   |
| 4-小明4-24                   |
+------------------------------+
4 rows in set (0.00 sec)

3.1 有一列为空,当前查询结果并不为空
3.2 但是如果分隔符为空,当前查询结果为空

  1. concat_ws(separator,str,str,str…)还可以把空进行替换
mysql>  select concat_ws('-',id,`name`,ifNULL(age,'==年龄为空了==')) from ct ;
+------------------------------------------------------------+
| concat_ws('-',id,`name`,ifNULL(age,'==年龄为空了=='))      |
+------------------------------------------------------------+
| 1-小明1-21                                                 |
| 2-小明2-==年龄为空了==                                     |
| 3-小明3-23                                                 |
| 4-小明4-24                                                 |
+------------------------------------------------------------+
4 rows in set (0.01 sec)

17 Date和String的互相转换

(DATE_FORMAT & STR_TO_DATE)

1.Date ——> String

使用的函数:DATE_FORMAT(date,format) date:需要转换的日期 format:格式化的样式

format样式整理:

    年:  %Y  显示四位 : 2015      %y   只显示后两位   :15
    月:  %M 月份的英文显示:October %m  月份的阿拉伯显示:01-12    %b 月份的英文缩略显示:Oct  %c  月份的阿拉伯显示:1-12
    日:  %d 阿拉伯显示:00-31       %D  带有英文后缀   :1st-31th     %e 阿拉伯显示:1-31          %j   年的天:001-366
    时:  %H :00-23       %h:01-12        %I:01-12     %k:0-23      %l:1-12
    分:  %i:00-59
    秒:  %S:00-59        %s:00-59
    微妙  %f
    AM/PM:%p
    12小时制时间: %r:   02:02:44 PM
    24小时制时间: %T:  14:02:44
    周: %W:周的英文显示      %w 周的阿拉伯显示 :0(星期日)-6(星期六)  %a   周的英文缩略显示:Mon-

举个例子:

DATE_FORMAT(now(),"%Y-%m-%d %T")   2015-09-01 17:10:52

DATE_FORMAT(now(),"%Y-%m-%d %H:%i:%s %p")     2015-09-01 17:10:52 PM

2.String ——>Date

使用的函数:STR_TO_DATE(str,format) str:字符形式的日期 format:格式化样式

举个例子:

STR_TO_DATE('1992-04-12',"%Y-%m-%d")   输出:1992-04-12(日期形式)

SELECT STR_TO_DATE('2017-01-06 10:20:30','%Y-%m-%d %H:%i:%s') AS result;

SELECT STR_TO_DATE('2017-01-06 10:20:30','%Y-%m-%d') AS result2;

18 MySQL的时间差函数的用法

时间差函数TIMESTAMPDIFF、DATEDIFF的用法

我们在写sql语句,尤其是存储过程中,会频繁用到对于日期、时间的比较和判断,那么对于这两个时间差比较函数用法做一个举例介绍。

datediff函数,返回值是相差的天数,不能定位到小时、分钟和秒。

– 相差2天

select datediff('2018-03-22 09:00:00', '2018-03-20 07:00:00');

TIMESTAMPDIFF函数,有参数设置,可以精确到天(DAY)、小时(HOUR),分钟(MINUTE)和秒(SECOND),使用起来比datediff函数更加灵活。对于比较的两个时间,时间小的放在前面,时间大的放在后面。

–相差1天

select TIMESTAMPDIFF(DAY, '2018-03-20 23:59:00', '2015-03-22 00:00:00');

–相差49小时

select TIMESTAMPDIFF(HOUR, '2018-03-20 09:00:00', '2018-03-22 10:00:00');

–相差2940分钟

select TIMESTAMPDIFF(MINUTE, '2018-03-20 09:00:00', '2018-03-22 10:00:00');

–相差176400秒

select TIMESTAMPDIFF(SECOND, '2018-03-20 09:00:00', '2018-03-22 10:00:00');

在存储过程中的写法:

注意:var_committime是前面业务中获取到需要比较的时间。

-- 获取当前时间
SET var_current_time = CONCAT(CURDATE(),' ',CURTIME());
-- 时间比较
SET var_time_diff = TIMESTAMPDIFF(MINUTE, var_committime, var_current_time);

-- 判断未审核的合同是否超过48小时未处理,如果超过则进行后续逻辑处理,否则不处理。
IF (var_time_diff > 2880) THEN

-- 相关业务逻辑处理

END IF;

总结:

1. mysql介绍和安装

2. mysql各种sql指令的操作和学习   (***************************************************************)

    数据库 (文件夹):

        增 create  database 数据库名;

        删 drop database 数据库名; 

        改 先删掉  在创建

        查 show databases;

    数据表 (文件):

        增:
            create table 表名 (
                列名 列属性  【not null/ null default ''】

            )engine=Innodb charset=utf8;

            ps:
                1. 最后一个不能加逗号
                2. 存储引擎  版本有关  (5.5 Innodb, 5.5以下 MyIsam)

        删除:
            drop table 表名;
            delete fromt  表名;
            truncate 表名;

        修改:
            alter table 表名 change 原列名  新列名 【类型  属性】;
            alter table 表名 drop 原列名;
            alter table 表名 add 新列名 【类型  属性】;

        查看:
            show tables;

    数据行(数据内容):

        增加:
            insert into 表名 (列名1, 列名2,...) values (值1, 值2,..);
            insert into 表名 (列名1, 列名2,...) values (值1, 值2,..),(值2, 值3),......;
            insert into 表名 (列名1, 列名2,...)select 列名1, 列名2,... from 另一张表;

        删除:    
            delete fromt  表名;
            delete fromt  表名 where id>10 and (or) id<10)(name='zzzzz');

        更新:
            update 表名 set 列名1=值1, 列名2=值2 
            update 表名 set 列名1=值1, 列名2=值2  where 条件

        查询:
            select * from 表名;

            select name, age from 表名;

            select * from 表名 where 条件 (> < = >= <=)

            select * from 表名 where name  in (1,2,3,4);

            select * from 表名 where id between 1 and 5;

            分页:
                select * from 表名 limit (page-1)*offset, offset;

            通配符匹配:
                select * from 表名 where name like '李%'select * from 表名 where name like '李_';

            排序:
                select * from 表名 order by id desc(降序), asc(升序);
                select * from 表名 order by id desc(降序), name asc(升序);

            分组聚合:
                select count(id) from 表名  group by name;
                select count(id) from 表名  group by name having count(id) > 3;


            连表:
                left join: 左连接  左边的表的数据完全显示  

                right join : 右连接 右边的表的数据完全显示

    外键:
        一对多:

            department:(一)
                id    name
                1      游戏部
                2      游戏部2


            user:
                ID    name     age    depart_id (多)
                1     zekai    18        1
                2     zekai2    28        1


            存在的问题:
                a. 部门名称得写多次
                b. 空间浪费
                c. 没有约束

            解决的方法:
                新建一张表, 然后depart_id 和 department中的主键自增id建立外键关系
                constraint 外键名(fk_) foreign key ('depart_id') references department ('id')

        一对一:
            user:
                ID    name     age   
                1     zekai    18        
                2     zekai2    28  

            blog:
                id    URL        uid (唯一索引 + 外键关联)
                 1    /zekai/     1
                 2    /zekai2     2

        多对多:
            user:
                ID    name     age      
                1     zekai    18      
                2     zekai2    28 

            host:
                ID    hostname   
                1       c1.com
                2       c2.com

            user2host:
                id   uid(外键)    hid(外键)  unique(uid, hid)
                1     1      1
                2     1      2
                3     2      1

3. 索引:
        作用: 加速查询速度
        场景:对经常使用的列加索引
        类型:
            主键索引: 加速查找 + 不能为空 + 不能重复   primary key
            唯一索引: 加速查找 + 可以为空 + 不能重复   unique(name)
                联合唯一索引:
                    加速查找 + 可以为空 + 不能重复  unique(name, age)
            普通索引: 加速查找 index(name)
                联合索引:
                    index(name, age)

            创建索引:
                第一种:
                    create table t1 (

                        id int ,
                        primary key (id)
                        unique uname (id),
                        index i_name (id)
                    )

                第二种:
                    create index ix_name on t1 (name);

            删除索引:
                drop index ix_name on t1;

            查看索引:
                show indexes for t1;

        索引类型:
            B+树


4. pymysql:
    conn = pymysql.connect()
    cursor = conn.cusor()
    sql = ''
    cursor.execute(sql)

    安全问题: 
        SQL注入
            原因:
                太相信用户的输入
            做法:
                sql = 'select * from t1 where id between %s and %s'
                cursor.execute(sql, (1,12))


5. 事务:
    ACID
    Innodb支持事务 MyISam不支持事务
    行锁            表锁

    存储文件格式:                存储文件格式:
        .frm: 表结构文件                .frm  :  表结构文件
        .idb: 表数据和索引文件            MYD  :  表数据文件
                                        .MYI  :  表的索引文件


6. mysqldump  -uroot -p  test > a.sql
   mysql    -uroot -p  test < a.sql

   mysqldump  -uroot -p  -B test > a.sql

7. 慢日志:
        slow

老师的笔记

文档更新时间: 2019-11-13 21:24   作者:李延召