zoukankan      html  css  js  c++  java
  • MySQL基本操作解析

    MySQL基本操作解析

    一、数据库概述

    二、MySQL下载与基本配置

    三、基本SQL语句

    四、库(database)操作详解

    五、表(table)操作详解

    六、数据(记录)操作详解

    七、pymysql模块

    八、视图、触发器、事务、存储过程、函数

    一、数据库概述

    什么是数据(what):

    用于记录显示世界中的某种状态。

    什么是记录(what):

    就相当于文件中一行内容(抽取事物一系列典型的特征拼到一起)。

    什么是表(what):

    相当于一个文件。

    什么是库(what):

    相当于一个文件夹。

    什么是数据库管理软件(what):

    相当于一个套接字服务端,数据库中的数据按一定的数据模型组织、描述和储存,具有较小的冗余度、较高的数据独立性和易扩展性,并可为各种 用户共享。

    什么是数据库服务器(what):

    运行有数据库管理软件的计算机。

    数据库本身就是一个C/S架构的套接字软件。

    常见的数据库:
    关系型:
    mysql
    mariadb
    oracle
    db2
    sqlserver

    非关系:
    存取数据都是以key:value
    mongodb
    redis
    memcache

    二、MySQL下载与基本配置

    1、Windows版本下载地址

    https://www.mysql.com/downloads/

    2、拷贝到存放路径解压即用

    3、修改精简文件名

    4、修改环境变量

    将mysql路径添加到path下的环境变量(用;分割)

    5、用管理员模式打开cmd.exe,通过cd命令切换到mysql路径(Windows下要加d)

    6、创建my.ini修改配置,设置默认账号、默认密码及识别的字符编码。

    
    
    #mysql5.5以上:修改方式有所改动

    [mysqld] character
    -set-server=utf8 collation-server=utf8_general_ci [client] default-character-set=utf8 user='root' password='' [mysql] default-character-set=utf8 user='root' password=''

    7、输入mysqld.exe --install,直接启动服务

    8、进入services.msc找到MySQL启动服务

    Tip:

    【破解密码登录】

    #1 关闭mysql
    #2 在cmd中执行:mysqld --skip-grant-tables
    #3 在cmd中执行:mysql
    #4 执行如下sql:
    update mysql.user set authentication_string=password('') where user = 'root';
    flush privileges;
    
    #5 tskill mysqld #或taskkill -f /PID 7832
    #6 重新启动mysql
    Windows版本
    [root@egon ~]# vim /etc/my.cnf    #mysql主配置文件
    [mysqld]
    skip-grant-table
    [root@egon ~]# systemctl restart mariadb
    [root@egon ~]# mysql
    MariaDB [(none)]> update mysql.user set password=password("123") where user="root" and host="localhost";
    MariaDB [(none)]> flush privileges;
    MariaDB [(none)]> q
    [root@egon ~]# #打开/etc/my.cnf去掉skip-grant-table,然后重启
    [root@egon ~]# systemctl restart mariadb
    [root@egon ~]# mysql -u root -p123 #以新密码登录
    Linux版本

    三、基本SQL语句

    SQL语言主要用于存取数据、查询数据、更新数据和管理关系数据库系统,SQL语言由IBM开发。SQL语言分为3种类型:
    #1、DDL语句    数据库定义语言: 数据库、表、视图、索引、存储过程,例如CREATE DROP ALTER
    #2、DML语句    数据库操纵语言: 插入数据INSERT、删除数据DELETE、更新数据UPDATE、查询数据SELECT
    #3、DCL语句    数据库控制语言: 例如控制用户的访问权限GRANT、REVOKE

     *****修改sql_mode模式*****

    默认模式为非严格模式,对于某些不符合限制的内容系统不会报错,会自行处理。

    严格模式在遇到不符合限制条件的语句会报错。

    修改sql_mode为严格模式,必须重启客户端才能生效。
    set global sql_mode="strict_trans_tables";
    select @@sql_mode;


    (一)库database(文件夹)

    增:create database db1 charset utf8;
    查:show databases;
    改:alter database db1 charset latin1;
    删: drop database db1;

    (二)表table(文件)

    *****先选择文件夹,也就是要操作的库*****
    select database(); 查看当前所在的库
    use db1;
    
    增:
    create table t1(id int,name char);
    create table db1.t1(id int,name char);

      create table t2(id int primary key auto_incremnt,name char(15)); # 限制id默认不能重复且自动排序
      insert into t2(name) values
      ('egon'),
      ('lxx'),
      ('wxx'),
      ('axx');

    
    
    删:
    drop table t1; #删除表
    
    改:
    alter table t1 add age int; #增加字段
    alter table t1 modify name char(15); #修改字段属性
    alter table t1 change name NAME char(15); #修改字段属性及修改字段名
    alter table t1 drop age; #删除字段
    
    查:
    show tables; #查看库下有哪些表
    show create table t1; #查看创建的表t1
    desc t1; #查看表内属性设置

    (三)记录(文件内容)

    增:
    insert into t1(id,name) values
    (1,'egon'),
    (2,'lxx'),
    (3,'alex');
    
    删:
    delete from db1.t1 where id >= 2; # 删除某条记录
    
    *****初始化表*****
    前文添加表时使用到了primary及key auto_increment来设置不可重复且自动排序,如果用delete from db1.t1 where id >= 2;删除记录,会导致继续添加记录时,新的id从删除部分
    继续计数。 可以使用truncate t2;进行初始化表 实际应用场景中,一般不建议删除记录,会在记录内添加一个状态来控制这条记录的状态。 改: update db1.t1 set name
    ='lxx_dsb' where id=2; 查: select id from db1.t1; select id,name from t1; select name,id from t1; select * from t1; select * from t1 where id >= 2;

    四、库(database)操作详解

    (一)创建数据库

    1.语法

    CREATE DATABASE 数据库名 charset utf8;

    2.命名规则

    可以由字母、数字、下划线、@、#、$
    区分大小写
    唯一性
    不能使用关键字如 create select
    不能单独使用数字
    最长128位

    (二)相关操作

    查看数据库
    show databases;
    show create database db1;
    select database();
    选择数据库
    USE 数据库名
    删除数据库
    DROP DATABASE 数据库名;
    修改数据库
    alter database db1 charset utf8;

    五、表(table)操作详解

    (一)创建表

    1.语法

    create table 表名(
    字段名1 类型[(宽度) 约束条件],
    字段名2 类型[(宽度) 约束条件],
    字段名3 类型[(宽度) 约束条件]
    );

    2.使用规则

    1.同一张表中字段名不能相同
    2.宽度与约束条件可选,字段名与类型是必须的
    3.约束条件是在数据类型之外对字段附加的额外限制
    4.最后一个字段之后不能加逗号

    3.数据类型

    ①整型

    整数类型:TINYINT SMALLINT MEDIUMINT INT BIGINT

    作用:存储年龄,等级,id,各种号码等

    #强调1:默认是有符号的
    create table t3(x tinyint);
    create table t4(x tinyint unsigned);
    # 强调2:整型类型后面的宽度限制的根本不是存储宽度,限制的是显示宽度
    create table t5(id int(1));
    create table t6(id int(5));

    ②浮点型

    定点数类型:DEC等同于DECIMAL  

    浮点类型:FLOAT DOUBLE

    作用:存储薪资、身高、体重、体质参数等

    ======================================
    #FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
    
    定义:
            单精度浮点数(非准确小数值),m是数字总个数,d是小数点后个数。m最大值为255,d最大值为30
    
    有符号:
               -3.402823466E+38 to -1.175494351E-38,
               1.175494351E-38 to 3.402823466E+38
    无符号:
               1.175494351E-38 to 3.402823466E+38
    
    
    精确度: 
               **** 随着小数的增多,精度变得不准确 ****
    
    
    ======================================
    #DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
    
    定义:
               双精度浮点数(非准确小数值),m是数字总个数,d是小数点后个数。m最大值为255,d最大值为30
    
    有符号:
               -1.7976931348623157E+308 to -2.2250738585072014E-308
               2.2250738585072014E-308 to 1.7976931348623157E+308
    
    无符号:
               2.2250738585072014E-308 to 1.7976931348623157E+308
                
    精确度:
               ****随着小数的增多,精度比float要高,但也会变得不准确 ****
    
    ======================================
    decimal[(m[,d])] [unsigned] [zerofill]
    
    定义:
              准确的小数值,m是数字总个数(负号不算),d是小数点后个数。 m最大值为65,d最大值为30。
    
    
    精确度:
               **** 随着小数的增多,精度始终准确 ****
               对于精确数值计算时需要用此类型
               decaimal能够存储精确值的原因在于其内部按照字符串存储。
    View Code
    float(255,30)
    double(255,30)
    decimal(65,30)
    
    create table t8(x float(255,30));
    create table t9(x double(255,30));
    create table t10(x decimal(65,30));
    
    insert into t8 values(1.111111111111111111111111111111);
    insert into t9 values(1.111111111111111111111111111111);
    insert into t10 values(1.111111111111111111111111111111);
    举例

    ③日期类型

    DATE TIME DATETIME TIMESTAMP YEAR 

    作用:存储用户注册时间,文章发布时间,员工入职时间,出生时间,过期时间等

    YEAR
                YYYY(1901/2155)
    
            DATE
                YYYY-MM-DD(1000-01-01/9999-12-31)
    
            TIME
                HH:MM:SS('-838:59:59'/'838:59:59')
    
            DATETIME
    
                YYYY-MM-DD HH:MM:SS(1000-01-01 00:00:00/9999-12-31 23:59:59    Y)
    
            TIMESTAMP
    
                YYYYMMDD HHMMSS(1970-01-01 00:00:00/2037 年某时)
    View Code
    year 1999
    date 1999-11-11
    time 08:30:00
    datetime/timestamp 1999-11-11 08:30:00
    
    create table student(
        id int primary key auto_increment,
        name char(16),
        born_year year,
        birth date,
        class_time time,
        reg_time datetime
    );
    insert into student(name,born_year,birth,class_time,reg_time) values
    ('egon1',now(),now(),now(),now());
    
    insert into student(name,born_year,birth,class_time,reg_time) values
    ('egon1',2000,20001111,now(),now());
    
    insert into student(name,born_year,birth,class_time,reg_time) values
    ('egon1',2000,'2000-11-11',083000,now());
    
    insert into student(name,born_year,birth,class_time,reg_time) values
    ('egon1',2000,'2000-11-11',"08:30:00",20171111111111);
    
    insert into student(name,born_year,birth,class_time,reg_time) values
    ('egon1',2000,'2000-11-11',"08:30:00","2017-11-11 11:11:11");
    
    create table t11(x timestamp);
    create table t12(x datetime not null default now());
    举例
    ============注意啦,注意啦,注意啦===========
    1. 单独插入时间时,需要以字符串的形式,按照对应的格式插入
    2. 插入年份时,尽量使用4位值
    3. 插入两位年份时,<=69,以20开头,比如50,  结果2050      
                    >=70,以19开头,比如71,结果1971

    ④字符类型

    *****注意:宽度指限制的是字符个数*****

    char类型:定长,简单粗暴,浪费空间,存取速度快

    char:定长
    char(5)

    varchar类型:变长,精准,节省空间,存取速度慢

    varchar:变长
    varchar(5)

    相同点:

    宽度指的都是最大存储的字符个数,超过了都无法正常存储
    不同点:
    char(5):
    'm'--->'m '5个字符

    varchar(5)
    'm'--->'m'1个字符

    *****注意*****

    mysql在查询时针对where 字段="值 "会忽略掉右面的空格,即where 字段="值"
    如果时like模糊匹配就不会忽略右面的空格了

    *****存储方式*****

    char(5)
    egon |axx |lxx |fm |

    varchar(5)
    1bytes+egon|1bytes+axx|1bytes+lxx|1bytes+fm|

    ⑤枚举与集合类型

    字段的值只能在给定范围中选择,如单选框,多选框
    enum 单选 只能在给定的范围内选一个值,如性别 sex 男male/女female
    set 多选 在给定的范围内可以选择一个或一个以上的值(爱好1,爱好2,爱好3...)

    枚举类型(enum)
                An ENUM column can have a maximum of 65,535 distinct elements. (The practical limit is less than 3000.)
                示例:
                    CREATE TABLE shirts (
                        name VARCHAR(40),
                        size ENUM('x-small', 'small', 'medium', 'large', 'x-large')
                    );
                    INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'),('polo shirt','small');
    
      
    
                集合类型(set)
                A SET column can have a maximum of 64 distinct members.
                示例:
                    CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));
                    INSERT INTO myset (col) VALUES ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
    View Code

    4.完整性约束

    约束条件与数据类型的宽度一样,都是可选参数

    作用:用于保证数据的完整性和一致性
    主要分为:

    PRIMARY KEY (PK)    标识该字段为该表的主键,可以唯一的标识记录
    FOREIGN KEY (FK)    标识该字段为该表的外键
    NOT NULL    标识该字段不能为空
    UNIQUE KEY (UK)    标识该字段的值是唯一的
    AUTO_INCREMENT    标识该字段的值自动增长(整数类型,而且为主键)
    DEFAULT    为该字段设置默认值
    
    UNSIGNED 无符号
    ZEROFILL 使用0填充

    说明:

    1. 是否允许为空,默认NULL,可设置NOT NULL,字段不允许为空,必须赋值
    2. 字段是否有默认值,缺省的默认值是NULL,如果插入记录时不给字段赋值,此字段使用默认值
    sex enum('male','female') not null default 'male'
    age int unsigned NOT NULL default 20 必须为正值(无符号) 不允许为空 默认是20
    3. 是否是key
    主键 primary key
    外键 foreign key
    索引 (index,unique...)

    ①primary key

    站在约束角度看primary key=not null unique,不能为空且唯一
    以后但凡建表,必须注意:
    1、必须有且只有一个主键
    2、通常是id字段被设置为主键

    create table t5(
        id int primary key auto_increment
    );

    ②foreign key

    限制关联表某一个字段的值必是来自于被关联表的一个字段的。

    # foreign key注意:
    # 1、被关联的字段必须是一个key,通常是id字段
    # 2、创建表时:必须先建立被关联的表,才能建立关联表
    create table dep(
        id int primary key auto_increment,
        dname varchar(20),
        info varchar(50)
    );
    
    
    create table emp(
        id int primary key auto_increment,
        name varchar(15),
        age int,
        dep_id int,
        foreign key(dep_id) references dep(id)
        on update cascade
        on delete cascade
    );
    # 3、插入记录时:必须先往被关联的表插入记录,才能往关联表中插入记录
    insert into dep(dname,info) values
    ('IT','技术能力有限部门xxx'),
    ('Sale','文化程度不高'),
    ('HR','招不到人部门');
    
    
    insert into emp(name,age,dep_id) values
    ('egon',18,1),
    ('alex',28,2),
    ('wsj',38,2),
    ('lxx',30,1),
    ('xiaohou',18,3);
    
    ps:删除时:应该先删除关联表emp中的记录,再删除被关联表对应的记录

    找表关系诀窍:

    emp        dep
    #1、先站在左表的角度:去找左表emp的多条记录能否对应右表dep的一条记录
        翻译:多个员工能否属于一个部门
    
    #2、然后站在右表的角度:去找右表dep的多条记录能否对应左表emp的一条记录
        翻译:多个部门能否拥有同一名员工
    # 多对一:结果的判断
    #1、如果只有单向的多对一成立,那么最终的关系就是多对一
    #2、在emp表新增一个字段dep_id, 该字段外键关联dep(id)
    # 多对多:结果的判断
    #1、双向的多对一就是多对多
    #2、需要建立第三张表,有一个字段值fk左表,一个字段的值fk右表
    create table author(
        id int primary key auto_increment,
        name varchar(16),
        age int
    );
    create table book(
        id int primary key auto_increment,
        bname varchar(20),
        price int
    );
    create table author2book(
        id int primary key auto_increment,
        author_id int,
        book_id int,
        foreign key(author_id) references author(id) on update cascade on delete cascade,
        foreign key(book_id) references book(id) on update cascade on delete cascade
    );
    # 一对一:无需参考窍门,左表的一条数据唯一对应右表的一条记录
    fk+unique

    ③not full

    是否可空,null表示空,非字符串
    not null - 不可空
    null - 可空


    默认值,创建列时可以指定默认值,当插入数据时如果未主动设置,则自动添加默认值
    create table tb1(
    nid int not null defalut 2,
    num int not null
    )

    create table t1(
        id int primary key auto_increment,
        name varchar(16) not null,
        sex enum('male','female') not null default 'male'
    );
    
    insert into t1(name) values('egon'),('lxx'),('alex');

    ④unique key

    约束数值唯一性

    方法一:

    create table t2(x int unique);

    方法二:

    create table t3(
        x int,
        y varchar(5),
        unique key(x)
    );

    方法三:constraint可定义联合唯一的key名,unique key(字段名1,字段名2)代表设置两个字段联合唯一

    create table service(
        ip varchar(15),
        port int,
        unique key(ip,port)
    );
    insert into service values
    ('1.1.1.1',3306),
    ('1.1.1.1',3306);

    方法四:not null+unique = primary

    mysql> create table t1(id int not null unique);
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> desc t1;
    +-------+---------+------+-----+---------+-------+
    | Field | Type    | Null | Key | Default | Extra |
    +-------+---------+------+-----+---------+-------+
    | id    | int(11) | NO   | PRI | NULL    |       |
    +-------+---------+------+-----+---------+-------+
    row in set (0.00 sec)
    
    not null+unique的化学反应

    ⑤auto_increment

    约束字段为自动增长,被约束的字段必须同时被key约束。

    create table t2(id int primary key auto_incremnt,name char(15));
            insert into t2(name) values
            ('egon'),
            ('lxx'),
            ('wxx'),
            ('axx');

    ⑥default

    设置默认值

    create table t1(
        id int primary key auto_increment,
        name varchar(16) not null,
        sex enum('male','female') not null default 'male'
    );
    
    insert into t1(name) values('egon'),('lxx'),('alex');

    (二)修改表

    语法:
    1. 修改表名
          ALTER TABLE 表名 
                              RENAME 新表名;
    
    2. 增加字段
          ALTER TABLE 表名
                              ADD 字段名  数据类型 [完整性约束条件…],
                              ADD 字段名  数据类型 [完整性约束条件…];
          ALTER TABLE 表名
                              ADD 字段名  数据类型 [完整性约束条件…]  FIRST;
          ALTER TABLE 表名
                              ADD 字段名  数据类型 [完整性约束条件…]  AFTER 字段名;
                                
    3. 删除字段
          ALTER TABLE 表名 
                              DROP 字段名;
    
    4. 修改字段
          ALTER TABLE 表名 
                              MODIFY  字段名 数据类型 [完整性约束条件…];
          ALTER TABLE 表名 
                              CHANGE 旧字段名 新字段名 旧数据类型 [完整性约束条件…];
          ALTER TABLE 表名 
                              CHANGE 旧字段名 新字段名 新数据类型 [完整性约束条件…];

    (三)复制表

    复制表结构+记录 (key不会复制: 主键、外键和索引)
    mysql> create table new_service select * from service;
    
    只复制表结构
    mysql> select * from service where 1=2;        //条件为假,查不到任何记录
    Empty set (0.00 sec)
    mysql> create table new1_service select * from service where 1=2;  
    Query OK, 0 rows affected (0.00 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    mysql> create table t4 like employees;

    (四)删除表

    DROP TABLE 表名;

    六、数据(记录)操作详解

    (一)插入数据insert

    1. 插入完整数据(顺序插入)
        语法一:
        INSERT INTO 表名(字段1,字段2,字段3…字段n) VALUES(值1,值2,值3…值n);
    
        语法二:
        INSERT INTO 表名 VALUES (值1,值2,值3…值n);
    
    2. 指定字段插入数据
        语法:
        INSERT INTO 表名(字段1,字段2,字段3…) VALUES (值1,值2,值3…);
    
    3. 插入多条记录
        语法:
        INSERT INTO 表名 VALUES
            (值1,值2,值3…值n),
            (值1,值2,值3…值n),
            (值1,值2,值3…值n);
            
    4. 插入查询结果
        语法:
        INSERT INTO 表名(字段1,字段2,字段3…字段n) 
                        SELECT (字段1,字段2,字段3…字段n) FROM 表2
                        WHERE …;

    (二)更新数据update

    语法:
        UPDATE 表名 SET
            字段1=值1,
            字段2=值2,
            WHERE CONDITION;
    
    示例:
        UPDATE mysql.user SET password=password(‘123’) 
            where user=’root’ and host=’localhost’;

    (三)删除数据delete

    语法:
        DELETE FROM 表名 
            WHERE CONITION;
    
    示例:
        DELETE FROM mysql.user 
            WHERE password=’’;
    
    练习:
        更新MySQL root用户密码为mysql123
        删除除从本地登录的root用户以外的所有用户

    (四)查询数据select

    1.单表查询

    a)语法

    SELECT 字段1,字段2... FROM 表名
                      WHERE 条件
                      GROUP BY field
                      HAVING 筛选
                      ORDER BY field
                      LIMIT 限制条数

    b)关键字执行顺序

    重点中的重点:关键字的执行优先级
    from
    where
    group by
    having
    select
    distinct
    order by
    limit

    c)简单查询

    company.employee
        员工id      id                  int             
        姓名        emp_name            varchar
        性别        sex                 enum
        年龄        age                 int
        入职日期     hire_date           date
        岗位        post                varchar
        职位描述     post_comment        varchar
        薪水        salary              double
        办公室       office              int
        部门编号     depart_id           int
    
    
    
    #创建表
    create table employee(
    id int not null unique auto_increment,
    name varchar(20) not null,
    sex enum('male','female') not null default 'male', #大部分是男的
    age int(3) unsigned not null default 28,
    hire_date date not null,
    post varchar(50),
    post_comment varchar(100),
    salary double(15,2),
    office int, #一个部门一个屋子
    depart_id int
    );
    
    
    #查看表结构
    mysql> desc employee;
    +--------------+-----------------------+------+-----+---------+----------------+
    | Field        | Type                  | Null | Key | Default | Extra          |
    +--------------+-----------------------+------+-----+---------+----------------+
    | id           | int(11)               | NO   | PRI | NULL    | auto_increment |
    | name         | varchar(20)           | NO   |     | NULL    |                |
    | sex          | enum('male','female') | NO   |     | male    |                |
    | age          | int(3) unsigned       | NO   |     | 28      |                |
    | hire_date    | date                  | NO   |     | NULL    |                |
    | post         | varchar(50)           | YES  |     | NULL    |                |
    | post_comment | varchar(100)          | YES  |     | NULL    |                |
    | salary       | double(15,2)          | YES  |     | NULL    |                |
    | office       | int(11)               | YES  |     | NULL    |                |
    | depart_id    | int(11)               | YES  |     | NULL    |                |
    +--------------+-----------------------+------+-----+---------+----------------+
    
    #插入记录
    #三个部门:教学,销售,运营
    insert into employee(name,sex,age,hire_date,post,salary,office,depart_id) values
    ('egon','male',18,'20170301','老男孩驻沙河办事处外交大使',7300.33,401,1), #以下是教学部
    ('alex','male',78,'20150302','teacher',1000000.31,401,1),
    ('wupeiqi','male',81,'20130305','teacher',8300,401,1),
    ('yuanhao','male',73,'20140701','teacher',3500,401,1),
    ('liwenzhou','male',28,'20121101','teacher',2100,401,1),
    ('jingliyang','female',18,'20110211','teacher',9000,401,1),
    ('jinxin','male',18,'19000301','teacher',30000,401,1),
    ('成龙','male',48,'20101111','teacher',10000,401,1),
    
    ('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
    ('丫丫','female',38,'20101101','sale',2000.35,402,2),
    ('丁丁','female',18,'20110312','sale',1000.37,402,2),
    ('星星','female',18,'20160513','sale',3000.29,402,2),
    ('格格','female',28,'20170127','sale',4000.33,402,2),
    
    ('张野','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
    ('程咬金','male',18,'19970312','operation',20000,403,3),
    ('程咬银','female',18,'20130311','operation',19000,403,3),
    ('程咬铜','male',18,'20150411','operation',18000,403,3),
    ('程咬铁','female',18,'20140512','operation',17000,403,3)
    ;
    
    #ps:如果在windows系统中,插入中文字符,select的结果为空白,可以将所有字符编码统一设置成gbk
    准备表和记录
    #简单查询
        SELECT id,name,sex,age,hire_date,post,post_comment,salary,office,depart_id 
        FROM employee;
    
        SELECT * FROM employee;
    
        SELECT name,salary FROM employee;
    
    #避免重复DISTINCT
        SELECT DISTINCT post FROM employee;    
    
    #通过四则运算查询
        SELECT name, salary*12 FROM employee;
        SELECT name, salary*12 AS Annual_salary FROM employee;
        SELECT name, salary*12 Annual_salary FROM employee;
    
    #定义显示格式
       CONCAT() 函数用于连接字符串
       SELECT CONCAT('姓名: ',name,'  年薪: ', salary*12)  AS Annual_salary 
       FROM employee;
       
       CONCAT_WS() 第一个参数为分隔符
       SELECT CONCAT_WS(':',name,salary*12)  AS Annual_salary 
       FROM employee;
    
       结合CASE语句:
       SELECT
           (
               CASE
               WHEN NAME = 'egon' THEN
                   NAME
               WHEN NAME = 'alex' THEN
                   CONCAT(name,'_BIGSB')
               ELSE
                   concat(NAME, 'SB')
               END
           ) as new_name
       FROM
           emp;

    d)where约束

    where字句中可以使用:

    1. 比较运算符:> < >= <= <> !=
    2. between 80 and 100 值在10到20之间
    3. in(80,90,100) 值是10或20或30
    4. like 'egon%'
        pattern可以是%或_,
        %表示任意多字符
        _表示一个字符 
    5. 逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not

    #1:单条件查询
        SELECT name FROM employee
            WHERE post='sale';
            
    #2:多条件查询
        SELECT name,salary FROM employee
            WHERE post='teacher' AND salary>10000;
    
    #3:关键字BETWEEN AND
        SELECT name,salary FROM employee 
            WHERE salary BETWEEN 10000 AND 20000;
    
        SELECT name,salary FROM employee 
            WHERE salary NOT BETWEEN 10000 AND 20000;
        
    #4:关键字IS NULL(判断某个字段是否为NULL不能用等号,需要用IS)
        SELECT name,post_comment FROM employee 
            WHERE post_comment IS NULL;
    
        SELECT name,post_comment FROM employee 
            WHERE post_comment IS NOT NULL;
            
        SELECT name,post_comment FROM employee 
            WHERE post_comment=''; 注意''是空字符串,不是null
        ps:
            执行
            update employee set post_comment='' where id=2;
            再用上条查看,就会有结果了
    
    #5:关键字IN集合查询
        SELECT name,salary FROM employee 
            WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ;
        
        SELECT name,salary FROM employee 
            WHERE salary IN (3000,3500,4000,9000) ;
    
        SELECT name,salary FROM employee 
            WHERE salary NOT IN (3000,3500,4000,9000) ;
    
    #6:关键字LIKE模糊查询
        通配符’%’
        SELECT * FROM employee 
                WHERE name LIKE 'eg%';
    
        通配符’_’
        SELECT * FROM employee 
                WHERE name LIKE 'al__';

    e)group by分组查询

    什么是分组(what):

    按照所有记录相同的部分进行归类,一定区分度低的字段。

    为什么要分组(why):

    当我们要以组为单位进行统计时就必须分组,分组的目的是为了以组为单位进行统计的,再去考虑单条记录毫无意义。

    聚合函数:

    max、min、avg、sum、count

    #强调:聚合函数聚合的是组的内容,若是没有分组,则默认一组
    
    示例:
        SELECT COUNT(*) FROM employee;
        SELECT COUNT(*) FROM employee WHERE depart_id=1;
        SELECT MAX(salary) FROM employee;
        SELECT MIN(salary) FROM employee;
        SELECT AVG(salary) FROM employee;
        SELECT SUM(salary) FROM employee;
        SELECT SUM(salary) FROM employee WHERE depart_id=3;

    注意:

    ①分组之后,只能查到分组的字段以及组内多条记录聚合的成果

    ②分组是在where之后发生的

    先设置模式:

    set global sql_mode="strict_trans_tables,only_full_group_by";

    语法:

    单独使用GROUP BY关键字分组
        SELECT post FROM employee GROUP BY post;
        注意:我们按照post字段分组,那么select查询的字段只能是post,想要获取组内的其他相关信息,需要借助函数
    
    GROUP BY关键字和GROUP_CONCAT()函数一起使用
        SELECT post,GROUP_CONCAT(name) FROM employee GROUP BY post;#按照岗位分组,并查看组内成员名
        SELECT post,GROUP_CONCAT(name) as emp_members FROM employee GROUP BY post;
    
    GROUP BY与聚合函数一起使用
        select post,count(id) as count from employee group by post;#按照岗位分组,并查看每个组有多少人

    (f)having过滤条件

    注意:

    ①where是在分组之前的过滤,即在分组之前做了一次整体性的筛选
    ②having是在分组之后的过滤,即在分组之后专门针对聚合的结果进行进一步的筛选

    mysql> select * from emp having salary > 100000;
    ERROR 1463 (42000): Non-grouping field 'salary' is used in HAVING clause
    
    mysql> select post,group_concat(name) from emp group by post having salary > 10000;#错误,分组后无法直接取到salary字段
    ERROR 1054 (42S22): Unknown column 'salary' in 'having clause'
    mysql> select post,group_concat(name) from emp group by post having avg(salary) > 10000;
    +-----------+-------------------------------------------------------+
    | post | group_concat(name) |
    +-----------+-------------------------------------------------------+
    | operation | 程咬铁,程咬铜,程咬银,程咬金,张野 |
    | teacher | 成龙,jinxin,jingliyang,liwenzhou,yuanhao,wupeiqi,alex |
    +-----------+-------------------------------------------------------+
    2 rows in set (0.00 sec)

    (g)order by 排序查询

    按单列排序
        SELECT * FROM employee ORDER BY salary;
        SELECT * FROM employee ORDER BY salary ASC;
        SELECT * FROM employee ORDER BY salary DESC;
    
    按多列排序:先按照age排序,如果年纪相同,则按照薪资排序
        SELECT * from employee
            ORDER BY age,
            salary DESC;

    (h)limit限制查询记录数

        SELECT * FROM employee ORDER BY salary DESC 
            LIMIT 3;                    #默认初始位置为0 
        
        SELECT * FROM employee ORDER BY salary DESC
            LIMIT 0,5; #从第0开始,即先查询出第一条,然后包含这一条在内往后查5条
    
        SELECT * FROM employee ORDER BY salary DESC
            LIMIT 5,5; #从第5开始,即先查询出第6条,然后包含这一条在内往后查5条

    (i)正则表达式查询

    SELECT * FROM employee WHERE name REGEXP '^ale';
    
    SELECT * FROM employee WHERE name REGEXP 'on$';
    
    SELECT * FROM employee WHERE name REGEXP 'm{2}';
    
    
    小结:对字符串匹配的方式
    WHERE name = 'egon';
    WHERE name LIKE 'yua%';
    WHERE name REGEXP 'on$';

    2.多表查询

    #建表
    create table department(
    id int,
    name varchar(20) 
    );
    
    create table employee(
    id int primary key auto_increment,
    name varchar(20),
    sex enum('male','female') not null default 'male',
    age int,
    dep_id int
    );
    
    #插入数据
    insert into department values
    (200,'技术'),
    (201,'人力资源'),
    (202,'销售'),
    (203,'运营');
    
    insert into employee(name,sex,age,dep_id) values
    ('egon','male',18,200),
    ('alex','female',48,201),
    ('wupeiqi','male',38,201),
    ('yuanhao','female',28,202),
    ('liwenzhou','male',18,200),
    ('jingliyang','female',18,204)
    ;
    
    
    #查看表结构和数据
    mysql> desc department;
    +-------+-------------+------+-----+---------+-------+
    | Field | Type | Null | Key | Default | Extra |
    +-------+-------------+------+-----+---------+-------+
    | id | int(11) | YES | | NULL | |
    | name | varchar(20) | YES | | NULL | |
    +-------+-------------+------+-----+---------+-------+
    
    mysql> desc employee;
    +--------+-----------------------+------+-----+---------+----------------+
    | Field | Type | Null | Key | Default | Extra |
    +--------+-----------------------+------+-----+---------+----------------+
    | id | int(11) | NO | PRI | NULL | auto_increment |
    | name | varchar(20) | YES | | NULL | |
    | sex | enum('male','female') | NO | | male | |
    | age | int(11) | YES | | NULL | |
    | dep_id | int(11) | YES | | NULL | |
    +--------+-----------------------+------+-----+---------+----------------+
    
    mysql> select * from department;
    +------+--------------+
    | id | name |
    +------+--------------+
    | 200 | 技术 |
    | 201 | 人力资源 |
    | 202 | 销售 |
    | 203 | 运营 |
    +------+--------------+
    
    mysql> select * from employee;
    +----+------------+--------+------+--------+
    | id | name | sex | age | dep_id |
    +----+------------+--------+------+--------+
    | 1 | egon | male | 18 | 200 |
    | 2 | alex | female | 48 | 201 |
    | 3 | wupeiqi | male | 38 | 201 |
    | 4 | yuanhao | female | 28 | 202 |
    | 5 | liwenzhou | male | 18 | 200 |
    | 6 | jingliyang | female | 18 | 204 |
    +----+------------+--------+------+--------+
    
    表department与employee
    准备表

    (一)笛卡尔积

    select * from emp,dep;
    
    select * from emp,dep where emp.dep_id = dep.id;
    
    select * from emp,dep where emp.dep_id = dep.id and dep.name = "技术";

    (二)内连接:只取两张表有对应关系的记录

    select * from emp inner join dep on emp.dep_id = dep.id;
    select * from emp inner join dep on emp.dep_id = dep.id
                                where dep.name = "技术";

    (三)左连接: 在内连接的基础上保留左表没有对应关系的记录

    select * from emp left join dep on emp.dep_id = dep.id;

    (四)右连接: 在内连接的基础上保留右表没有对应关系的记录

    select * from emp right join dep on emp.dep_id = dep.id;

    (五)全连接:在内连接的基础上保留左、右面表没有对应关系的的记录

    select * from emp left join dep on emp.dep_id = dep.id
    union
    select * from emp right join dep on emp.dep_id = dep.id;

    (六)子查询

    #1:子查询是将一个查询语句嵌套在另一个查询语句中。
    #2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
    #3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
    #4:还可以包含比较运算符:= 、 !=、> 、<等
    #查询平均年龄在25岁以上的部门名
    select id,name from department
        where id in 
            (select dep_id from employee group by dep_id having avg(age) > 25);
    
    #查看技术部员工姓名
    select name from employee
        where dep_id in 
            (select id from department where name='技术');
    
    #查看不足1人的部门名(子查询得到的是有人的部门id)
    select name from department where id not in (select distinct dep_id from employee);
    带in关键字
    #比较运算符:=、!=、>、>=、<、<=、<>
    #查询大于所有人平均年龄的员工名与年龄
    mysql> select name,age from emp where age > (select avg(age) from emp);
    +---------+------+
    | name | age |
    +---------+------+
    | alex | 48 |
    | wupeiqi | 38 |
    +---------+------+
    rows in set (0.00 sec)
    
    
    #查询大于部门内平均年龄的员工名、年龄
    select t1.name,t1.age from emp t1
    inner join 
    (select dep_id,avg(age) avg_age from emp group by dep_id) t2
    on t1.dep_id = t2.dep_id
    where t1.age > t2.avg_age;
    带比较运算符
    #department表中存在dept_id=203,Ture
    mysql> select * from employee
        ->     where exists
        ->         (select id from department where id=200);
    +----+------------+--------+------+--------+
    | id | name       | sex    | age  | dep_id |
    +----+------------+--------+------+--------+
    |  1 | egon       | male   |   18 |    200 |
    |  2 | alex       | female |   48 |    201 |
    |  3 | wupeiqi    | male   |   38 |    201 |
    |  4 | yuanhao    | female |   28 |    202 |
    |  5 | liwenzhou  | male   |   18 |    200 |
    |  6 | jingliyang | female |   18 |    204 |
    +----+------------+--------+------+--------+
    
    #department表中存在dept_id=205,False
    mysql> select * from employee
        ->     where exists
        ->         (select id from department where id=204);
    Empty set (0.00 sec)
    带exist关键字

    七、pymysql模块 

    #安装
    pip3 install pymysql

    (一)创建连接,创建游标,执行sql,关闭游标

    import pymysql
    user=input('用户名: ').strip()
    pwd=input('密码: ').strip()
    
    #链接
    conn=pymysql.connect(host='localhost',user='root',password='123',database='egon',charset='utf8')
    #游标
    cursor=conn.cursor() #执行完毕返回的结果集默认以元组显示
    #cursor=conn.cursor(cursor=pymysql.cursors.DictCursor)
    
    
    #执行sql语句
    sql='select * from userinfo where name="%s" and password="%s"' %(user,pwd) #注意%s需要加引号
    print(sql)
    res=cursor.execute(sql) #执行sql语句,返回sql查询成功的记录数目
    print(res)
    
    cursor.close()
    conn.close()
    
    if res:
        print('登录成功')
    else:
        print('登录失败')

    (二)execute()之sql注入

    最后那一个空格,在一条sql语句中如果遇到select * from t1 where id > 3 -- and name='egon';则--之后的条件被注释掉了
    
    #1、sql注入之:用户存在,绕过密码
    egon' -- 任意字符
    
    #2、sql注入之:用户不存在,绕过用户与密码
    xxx' or 1=1 -- 任意字符

    解决方法:

    解决 sql注入问题
    pip3 install pymysql
    import pymysql
    
    client=pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='egon123',
        database='db6',
        charset='utf8'
    )
    
    cursor=client.cursor()
    #查询
    inp_user=input('输入账号名: ').strip()
    inp_pwd=input('输入密码: ').strip()
    
    sql='select id from user where name = %s and pwd = %s;'
    rows=cursor.execute(sql,(inp_user,inp_pwd))
    if rows:
        print('33[45m登陆成功33[0m')
    else:
        print('33[46m用户名或密码错误33[0m')
    
    cursor.close()
    client.close()

    (三)增,删,改commit() 

    import pymysql
    
    client=pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='egon123',
        database='db6',
        charset='utf8'
    )
    
    cursor=client.cursor()
    
    # sql='insert into t1 values(3,"alex"),(4,"lxx");'
    # userinfo=[
    #     (3,"alex"),
    #     (4,"lxx"),
    #     (5,"yxx")
    # ]
    # for user in userinfo:
    #     sql='insert into t1 values(%s,"%s");' %(user[0],user[1])
    #     # print(sql)
    #     cursor.execute(sql)
    
    # sql='insert into t1 values(%s,%s);'
    # cursor.executemany(sql,userinfo)
    
    cursor.execute('delete from t1 where id=3;')
    
    client.commit()
    
    cursor.close()
    client.close()

     (四)查fetchone,fetchall,fetchmany

    import pymysql
    #链接
    conn=pymysql.connect(host='localhost',user='root',password='123',database='egon')
    #游标
    cursor=conn.cursor()
    
    #执行sql语句
    sql='select * from userinfo;'
    rows=cursor.execute(sql) #执行sql语句,返回sql影响成功的行数rows,将结果放入一个集合,等待被查询
    
    # cursor.scroll(3,mode='absolute') # 相对绝对位置移动
    # cursor.scroll(3,mode='relative') # 相对当前位置移动
    res1=cursor.fetchone()
    res2=cursor.fetchone()
    res3=cursor.fetchone()
    res4=cursor.fetchmany(2)
    res5=cursor.fetchall()
    print(res1)
    print(res2)
    print(res3)
    print(res4)
    print(res5)
    print('%s rows in set (0.00 sec)' %rows)
    
    
    
    conn.commit() #提交后才发现表中插入记录成功
    cursor.close()
    conn.close()
    
    '''
    (1, 'root', '123456')
    (2, 'root', '123456')
    (3, 'root', '123456')
    ((4, 'root', '123456'), (5, 'root', '123456'))
    ((6, 'root', '123456'), (7, 'lhf', '12356'), (8, 'eee', '156'))
    rows in set (0.00 sec)
    '''

    八、视图、触发器、事务、存储过程、函数

    (一)视图

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

    # 强调
    #1、字段名不能重复
    #2、视图是为了简化查询的sql语句,不应该修改视图中的记录
    create view emp2dep as select emp.*,dep.name as dep_name from emp inner join dep on emp.dep_id = dep.id;

    (二)触发器

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

    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代表执行失败
    );
    
    CREATE TABLE errlog (
        id INT PRIMARY KEY auto_increment,
        err_id int
    );
    
    delimiter $$
    CREATE TRIGGER tri_after_insert_cmd AFTER INSERT ON cmd FOR EACH ROW
    BEGIN
        if NEW.success = 'no' then
            insert into errlog(err_id) values(NEW.id);
        end if;
    END $$
    delimiter ;
    
    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');

    特别的:NEW表示即将插入的数据行,OLD表示即将删除的数据行。

    (三)事务

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

    多数用于交易类需求。

    #transaction:事务,交易
    # 事务可以包含一系列的sql语句,事务的执行具有原子性
    #1、原子性:
    #包含多条sql语句要么都执行成功,要么都执行不成功
    #2、回滚
    
    create table user(
    id int primary key auto_increment,
    name char(32),
    balance int
    );
    
    insert into user(name,balance)
    values
    ('wsb',1000),
    ('egon',1000),
    ('ysb',1000);
    
    
    start transaction;
    try:
        update user set balance=900 where id=1;
        update user set balance=1010 where id=2;
        update user set balance=1090 where id=3;
        commit;
    except Exception:
        rollback;

    (四)存储过程

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

    方案一:
    应用程序:
    mysql:编写存储过程

    方案二:
    应用程序:原生sql
    mysql:

    方案三:
    应用程序:ORM(类/对象 --->原生sql)
    mysql:


    执行效率:
    方案一 > 方案二 -> 方案三

    开发效率:
    方案一 > 方案三 -> 方案二

    简单存储过程【无参】

    delimiter //
    create procedure p1()
    BEGIN
        select * from blog;
        INSERT into blog(name,sub_time) values("xxx",now());
    END //
    delimiter ;
    
    #在mysql中调用
    call p1() 
    
    #在python中基于pymysql调用
    cursor.callproc('p1') 
    print(cursor.fetchall())
    View Code

    存储过程【有参】

    对于存储过程,可以接收参数,其参数有三类:
    
    #in          仅用于传入参数用
    #out        仅用于返回值用
    #inout     既可以传入又可以当作返回值
    delimiter //
    create procedure p2(
        in n1 int,
        in n2 int
    )
    BEGIN
        
        select * from blog where id > n1;
    END //
    delimiter ;
    
    #在mysql中调用
    call p2(3,2)
    
    #在python中基于pymysql调用
    cursor.callproc('p2',(3,2))
    print(cursor.fetchall())
    
    in:传入参数
    in
    delimiter //
    create procedure p3(
        in n1 int,
        out res int
    )
    BEGIN
        select * from blog where id > n1;
        set res = 1;
    END //
    delimiter ;
    
    #在mysql中调用
    set @res=0; #0代表假(执行失败),1代表真(执行成功)
    call p3(3,@res);
    select @res;
    
    #在python中基于pymysql调用
    cursor.callproc('p3',(3,0)) #0相当于set @res=0
    print(cursor.fetchall()) #查询select的查询结果
    
    cursor.execute('select @_p3_0,@_p3_1;') #@p3_0代表第一个参数,@p3_1代表第二个参数,即返回值
    print(cursor.fetchall())
    
    out:返回值
    out
    delimiter //
    create procedure p4(
        inout n1 int
    )
    BEGIN
        select * from blog where id > n1;
        set n1 = 1;
    END //
    delimiter ;
    
    #在mysql中调用
    set @x=3;
    call p4(@x);
    select @x;
    
    
    #在python中基于pymysql调用
    cursor.callproc('p4',(3,))
    print(cursor.fetchall()) #查询select的查询结果
    
    cursor.execute('select @_p4_0;') 
    print(cursor.fetchall())
    
    inout:既可以传入又可以返回
    inout

    执行存储过程

    -- 无参数
    call proc_name()
    
    -- 有参数,全in
    call proc_name(1,2)
    
    -- 有参数,有in,out,inout
    set @t1=0;
    set @t2=3;
    call proc_name(1,2,@t1,@t2)
    
    执行存储过程
    
    在MySQL中执行存储过程
    mysql中执行存储过程
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import pymysql
    
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 执行存储过程
    cursor.callproc('p1', args=(1, 22, 3, 4))
    # 获取执行完存储的参数
    cursor.execute("select @_p1_0,@_p1_1,@_p1_2,@_p1_3")
    result = cursor.fetchall()
    
    conn.commit()
    cursor.close()
    conn.close()
    
    
    print(result)
    
    在python中基于pymysql执行存储过程
    python中基于pymysql执行存储过程

    (五)函数

    一、数学函数
        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        
            
    七、控制流函数小练习
    #7.1、准备表
    /*
    Navicat MySQL Data Transfer
    
    Source Server         : localhost_3306
    Source Server Version : 50720
    Source Host           : localhost:3306
    Source Database       : student
    
    Target Server Type    : MYSQL
    Target Server Version : 50720
    File Encoding         : 65001
    
    Date: 2018-01-02 12:05:30
    */
    
    SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for course
    -- ----------------------------
    DROP TABLE IF EXISTS `course`;
    CREATE TABLE `course` (
      `c_id` int(11) NOT NULL,
      `c_name` varchar(255) DEFAULT NULL,
      `t_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`c_id`),
      KEY `t_id` (`t_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of course
    -- ----------------------------
    INSERT INTO `course` VALUES ('1', 'python', '1');
    INSERT INTO `course` VALUES ('2', 'java', '2');
    INSERT INTO `course` VALUES ('3', 'linux', '3');
    INSERT INTO `course` VALUES ('4', 'web', '2');
    
    -- ----------------------------
    -- Table structure for score
    -- ----------------------------
    DROP TABLE IF EXISTS `score`;
    CREATE TABLE `score` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `s_id` int(10) DEFAULT NULL,
      `c_id` int(11) DEFAULT NULL,
      `num` double DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of score
    -- ----------------------------
    INSERT INTO `score` VALUES ('1', '1', '1', '79');
    INSERT INTO `score` VALUES ('2', '1', '2', '78');
    INSERT INTO `score` VALUES ('3', '1', '3', '35');
    INSERT INTO `score` VALUES ('4', '2', '2', '32');
    INSERT INTO `score` VALUES ('5', '3', '1', '66');
    INSERT INTO `score` VALUES ('6', '4', '2', '77');
    INSERT INTO `score` VALUES ('7', '4', '1', '68');
    INSERT INTO `score` VALUES ('8', '5', '1', '66');
    INSERT INTO `score` VALUES ('9', '2', '1', '69');
    INSERT INTO `score` VALUES ('10', '4', '4', '75');
    INSERT INTO `score` VALUES ('11', '5', '4', '66.7');
    
    -- ----------------------------
    -- Table structure for student
    -- ----------------------------
    DROP TABLE IF EXISTS `student`;
    CREATE TABLE `student` (
      `s_id` varchar(20) NOT NULL,
      `s_name` varchar(255) DEFAULT NULL,
      `s_age` int(10) DEFAULT NULL,
      `s_sex` char(1) DEFAULT NULL,
      PRIMARY KEY (`s_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of student
    -- ----------------------------
    INSERT INTO `student` VALUES ('1', '鲁班', '12', '');
    INSERT INTO `student` VALUES ('2', '貂蝉', '20', '');
    INSERT INTO `student` VALUES ('3', '刘备', '35', '');
    INSERT INTO `student` VALUES ('4', '关羽', '34', '');
    INSERT INTO `student` VALUES ('5', '张飞', '33', '');
    
    -- ----------------------------
    -- Table structure for teacher
    -- ----------------------------
    DROP TABLE IF EXISTS `teacher`;
    CREATE TABLE `teacher` (
      `t_id` int(10) NOT NULL,
      `t_name` varchar(50) DEFAULT NULL,
      PRIMARY KEY (`t_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of teacher
    -- ----------------------------
    INSERT INTO `teacher` VALUES ('1', '大王');
    INSERT INTO `teacher` VALUES ('2', 'alex');
    INSERT INTO `teacher` VALUES ('3', 'egon');
    INSERT INTO `teacher` VALUES ('4', 'peiqi');
    
    #7.2、统计各科各分数段人数.显示格式:课程ID,课程名称,[100-85],[85-70],[70-60],[ <60]
    
    select  score.c_id,
              course.c_name, 
          sum(CASE WHEN num BETWEEN 85 and 100 THEN 1 ELSE 0 END) as '[100-85]',
          sum(CASE WHEN num BETWEEN 70 and 85 THEN 1 ELSE 0 END) as '[85-70]',
          sum(CASE WHEN num BETWEEN 60 and 70 THEN 1 ELSE 0 END) as '[70-60]',
          sum(CASE WHEN num < 60 THEN 1 ELSE 0 END) as '[ <60]'
    from score,course where score.c_id=course.c_id GROUP BY score.c_id;
    内置函数
    #1 基本使用
    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'
    
    
    #2 准备表和记录
    CREATE TABLE blog (
        id INT PRIMARY KEY auto_increment,
        NAME CHAR (32),
        sub_time datetime
    );
    
    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');
    
    #3. 提取sub_time字段的值,按照格式后的结果即"年月"来分组
    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 |
    +-------------------------------+----------+
    rows in set (0.00 sec)
    
    需要掌握函数:date_format
    需要掌握的函数date_format

    (六)流程控制

    条件判断:

    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条件语句
    if

    循环语句:

    delimiter //
    CREATE PROCEDURE proc_while ()
    BEGIN
    
        DECLARE num INT ;
        SET num = 0 ;
        WHILE num < 10 DO
            SELECT
                num ;
            SET num = num + 1 ;
        END WHILE ;
    
    END //
    delimiter ;
    
    while循环
    while
    delimiter //
    CREATE PROCEDURE proc_repeat ()
    BEGIN
    
        DECLARE i INT ;
        SET i = 0 ;
        repeat
            select i;
            set i = i + 1;
            until i >= 5
        end repeat;
    
    END //
    delimiter ;
    
     repeat循环
    repeat
    BEGIN
        
        declare i int default 0;
        loop_label: loop
            
            set i=i+1;
            if i<8 then
                iterate loop_label;
            end if;
            if i>=10 then
                leave loop_label;
            end if;
            select i;
        end loop loop_label;
    
    END
    
    loop
    loop
  • 相关阅读:
    Linux用户管理
    chattr&lsattr
    repo 回退当前分支下所有仓库到指定日期前的最新代码版本
    grep
    awk
    vscode sftp插件的使用
    程序的链接
    ZJOI2015 诸神眷顾的幻想乡
    BZOJ3756 Pty的字符串
    HDU1506 Largest Rectangle in a Histogram
  • 原文地址:https://www.cnblogs.com/neymargoal/p/9333912.html
Copyright © 2011-2022 走看看