zoukankan      html  css  js  c++  java
  • Mysql的视图、存储过程、函数、索引全解析

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

    1创建视图

    --格式:CREATE VIEW 视图名称 AS  SQL语句

    CREATE VIEW v1 AS

    SELET nid,

        name

    FROM

        A

    WHERE

    nid > 4

    2删除视图

    --格式:DROP VIEW 视图名称

    DROP VIEW v1

    3修改视图

    -- 格式:ALTER VIEW 视图名称 AS SQL语句

    ALTER VIEW v1 AS

    SELET A.nid,

        B. NAME

    FROM

        A

    LEFT JOIN B ON A.id = B.nid

    LEFT JOIN C ON A.id = C.nid

    WHERE

        A.id > 2

    AND C.nid < 5

    4使用视图

    视图的使用和普通表一样,由于视图是虚拟表,所以无法对其真实表进行创建、更新和删除操作,仅做查询用。

    select * from v1

    二、触发器

    对某个表进行【增/删/改】操作的前后触发一些操作即为触发器,如果希望触发增删改的行为之前或之后做操作时,可以使用触发器,触发器用于自定义用户对表的行进行【增/删/改】前后的行为。

    1基本语法

    # 插入前

    CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW

    BEGIN

        ...

    END

    # 插入后

    CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW

    BEGIN

        ...

    END

    # 删除前

    CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW

    BEGIN

        ...

    END

    # 删除后

    CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW

    BEGIN

        ...

    END

    # 更新前

    CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW

    BEGIN

        ...

    END

    # 更新后

    CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW

    BEGIN

        ...

    END

    2创建触发器

    创建触发器基本语法是以下code:

    但有一点要注意,触发器内关键字NEW表示即将插入的数据行,OLD表示即将删除的数据行。

    # 插入前触发器

    delimiter //

    CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW

    BEGIN

    IF NEW. NAME == 'nick' THEN

        INSERT INTO tb2 (NAME)

    VALUES

        ('aa')

    END

    END//

    delimiter ;

    # 插入后触发器

    delimiter //

    CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW

    BEGIN

        IF NEW. num = 666 THEN

            INSERT INTO tb2 (NAME)

            VALUES

                ('666'),

                ('666') ;

        ELSEIF NEW. num = 555 THEN

            INSERT INTO tb2 (NAME)

            VALUES

                ('555'),

                ('555') ;

        END IF;

    END//

    delimiter 

    3删除触发器

    DROP TRIGGER tri_after_insert_tb1;

    4使用触发器

    触发器是由于对表的增、删、改操作时被动执行的。

    insert into tb1(num) values(666)

    三、存储过程

    存储过程是一个SQL语句集合,类似函数,需要主动调用。

    1创建存储过程

    # 无参数存储过程

    # 创建存储过程

    delimiter //

    create procedure p1()

    BEGIN

        select * from t1;

    END//

    delimiter ;

    # 执行存储过程

    call p1()

    都说了类似函数,那必须得可以接收参数,且参数有三类:

    • in          仅用于传入参数用

    • out        仅用于返回值用

    • inout     既可以传入又可以当作返回值

    # 有参数存储过程

    # 创建存储过程

    delimiter \    # 结尾分号改为\

    create procedure p1(

        in i1 int,

        in i2 int,

        inout i3 int,

        out r1 int

    )

    BEGIN

        DECLARE temp1 int;    # 创建申明局部变量

        DECLARE temp2 int default 0;

        set temp1 = 1;

        set r1 = i1 + i2 + temp1 + temp2;

        set i3 = i3 + 100;

    end\

    delimiter ;

    # 执行存储过程

    DECLARE @t1 INT default 3;

    DECLARE @t2 INT;

    CALL p1 (1, 2 ,@t1, @t2);

    SELECT @t1,@t2;

    2删除存储过程drop procedure proc_name;

    3执行存储过程

    执行为函数名加括号;

    DECLARE代表创建一个局部变量

    # 无参数

    call proc_name()

    # 有参数,全in

    call proc_name(1,2)

    # 有参数,有in,out,inout

    DECLARE @t1 INT;

    DECLARE @t2 INT default 3;

    call proc_name(1,2,@t1,@t2)

    • pymysql执行存储过程

    四、函数

    该讲讲真正的函数了,与存储过程不同的是有return值。

    1自定义函数

    delimiter \

    create function f1(

        i1 int,

        i2 int)

    returns int

    BEGIN

        declare num int;

        set num = i1 + i2;

        return(num);

    END \

    delimiter ;

    2删除函数

    drop function func_name;

    3执行函数

    # 获取返回值

    declare @i VARCHAR(32);

    select UPPER('nick') into @i;

    SELECT @i;

    # 在查询中使用

    select f1(11,nid) ,name from tb2;

    4内置函数

    当然MySQL也不例外,有着非常好用的内置函数。






    五、事务

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

    delimiter 为改变结束符号,默认";"

    # 支持事务的存储过程

    delimiter \

    create PROCEDURE p1(

        OUT p_return_code tinyint

    )

    BEGIN

      DECLARE exit handler for sqlexception

      BEGIN

        -- ERROR

        set p_return_code = 1;

        rollback;

      END;

      DECLARE exit handler for sqlwarning

      BEGIN

        -- WARNING

        set p_return_code = 2;

        rollback;

      END;

      START TRANSACTION;

        DELETE from tb1;

        insert into tb2(name)values('seven');

      COMMIT;

      -- SUCCESS

      set p_return_code = 0;

      END\

    delimiter ;

    # 执行存储过程

    DECLARE @i TINYINT;

    call p1(@i);

    select @i;

    六、索引

    1索引概述

    • 索引是表的索引目录,在查找内容之前先查目录中查找索引位置,从而快速定位查询数据;

    • 可以理解成新华字典中的索引;

    • 索引会保存在额外的文件中。

    2索引种类

    一般的索引种类及功能:

    • 普通索引:仅加速查询

    • 唯一索引:加速查询 + 列值唯一(可以有null)

    • 主键索引:加速查询 + 列值唯一 + 表中只有一个(不可以有null)

    • 组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并

    • 全文索引:对文本的内容进行分词,进行搜索 

    • 索引合并:使用多个单列索引组合查询搜索。

    • 覆盖索引:select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。

    a、普通索引

    # 创建表 + 索引

    create table in1(

        nid int not null auto_increment primary key,

        name varchar(32) not null,

        email varchar(64) not null,

        extra text,

        index ix_name (name)

    )

    # 创建索引

    create index index_name on table_name(column_name)

    # 删除索引

    drop index_name on table_name;

    # 查看索引

    show index from table_name;

    #注意:对于创建索引时如果是BLOB 和 TEXT 类型,必须指定length。

    create index ix_extra on in1(extra(32));

    b、唯一索引

    # 创建表 + 唯一索引

    create table in1(

        nid int not null auto_increment primary key,

        name varchar(32) not null,

        email varchar(64) not null,

        extra text,

        unique ix_name (name)

    )

    # 创建唯一索引

    create unique index 索引名 on 表名(列名)

    # 删除唯一索引

    drop unique index 索引名 on 表名

    c、主键索引

    # 创建表 + 创建主键

    create table in1(

        nid int not null auto_increment primary key,

        name varchar(32) not null,

        email varchar(64) not null,

        extra text,

        index ix_name (name)

    )

    OR

    create table in1(

        nid int not null auto_increment,

        name varchar(32) not null,

        email varchar(64) not null,

        extra text,

        primary key(ni1),

        index ix_name (name)

    )

    # 创建主键

    alter table 表名 add primary key(列名);

    # 删除主键

    alter table 表名 drop primary key;

    alter table 表名  modify  列名 int, drop primary key;

    d、组合索引

    组合索引是多个列组合成一个索引来查询。

    应用场景:频繁的同时使用多列来进行查询,如:where name = 'nick' and age = 18。

    # 创建表

    create table mess(

        nid int not null auto_increment primary key,

        name varchar(32) not null,

        age int not null

    )

    # 创建组合索引

    create index ix_name_age on mess(name,age);

    如上创建组合索引之后,查询一定要注意:

    • name and email  -- >使用索引,name一定要放前面

    • name                 -- >使用索引

    • email                 -- >不使用索引

    注意:同时搜索多个条件时,组合索引的性能效率好过于多个单一索引合并。

    3相关命令

    # 查看索引

        show index from  表名

    # 查看执行时间

        set profiling = 1;  # 开启profiling

        SQL...              # 执行SQL语句

        show profiles;      # 查看结果

    4如何正确使用索引

    # like '%xx',避免%_写在开头

        select * from tb1 where name like '%n';

    # 使用函数

        select * from tb1 where reverse(name) = 'nick';

    # or

        select * from tb1 where nid = 1 or email = '630571017@qq.com';

        注:当or条件中有未建立索引的列才失效,否则会走索引

    # 类型不一致

        如果列是字符串类型,传入条件是必须用引号引起来。

        select * from tb1 where name = 999;

    # !=,不等于

        select * from tb1 where name != 'nick'

        注:如果是主键,则还是会走索引

            select * from tb1 where nid != 123

    # >,大于

        select * from tb1 where name > 'nick'

        注:如果是主键或索引是整数类型,则还是会走索引

            select * from tb1 where nid > 123

            select * from tb1 where num > 123

    # order by

        select email from tb1 order by name desc;

        当根据索引排序时候,选择的映射如果不是索引,则不走索引

        注:如果对主键排序,则还是走索引:

            select * from tb1 order by nid desc;

    # 组合索引最左前缀

        如果组合索引为:(name,email),查询使用:

        name and email       -- 使用索引

        name                 -- 使用索引

        email                -- 不使用索引

    5注意事项

    # 避免使用select *

    # count(1)或count(列) 代替 count(*)

    # 创建表时尽量时 char 代替 varchar

    # 表的字段顺序固定长度的字段优先

    # 组合索引代替多个单列索引(经常使用多个条件查询时)

    # 尽量使用短索引

    # 使用连接(JOIN)来代替子查询(Sub-Queries)

    # 连表时注意条件类型需一致

    # 索引散列值(重复少)不适合建索引,例:性别不适合

    6执行计划

    explain + 查询SQL  用于显示SQL执行信息参数,根据参考信息可以进行SQL优化。

    id

            查询顺序标识

              

            特别的:如果使用union连接气值可能为null



    7慢日志查询

    日志可以记录哪些查询语句慢,没有走索引,用户发现问题,从而解决优化

    a、配置MySQL自动记录慢日志

     修改配置文件 my.ini,没有则添加

    slow_query_log = OFF                   # 是否开启慢日志记录

    long_query_time = 2                    # 时间限制,超过此时间,则记录

    slow_query_log_file = /usr/slow.log    # 日志文件

    log_queries_not_using_indexes = OFF    # 为使用索引的搜索是否记录

    # 查看当前配置信息:

       show variables like '%query%'

    # 修改当前配置:

       set global 变量名 = 值

    b、查看MySQL慢日志

     

    七、其它

    自然所有的东西都离不开基本的语法语句啦,循环语句与判断语句

    1条件语句

    if then elseif then else end if

    # if条件语句

    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 ;

    2循环语句

    分为三种循环语句:while循环、repeat循环、loop循环。

    # while循环

    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 ;

    # repeat循环,相当于 do 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 ;

    # loop

    delimiter \

    CREATE PROCEDURE proc_loop ()

    BEGIN

        declare i int default 0;

        loop_label: loop

            select i;

            set i=i+1;

            if i>=5 then

                leave loop_label;

                end if;

        end loop;

    END\

    delimiter ;

    3动态执行SQL语句

    # 动态执行SQL

    delimiter \

    DROP PROCEDURE IF EXISTS proc_sql \

    CREATE PROCEDURE proc_sql ()

    BEGIN

        declare p1 int;

        set p1 = 11;

        set @p1 = p1;

        PREPARE prod FROM 'select * from tb2 where nid > ?';

        EXECUTE prod USING @p1;

        DEALLOCATE prepare prod;

    END\

    delimiter ;

    # 方式二

    delimiter \

    DROP PROCEDURE IF EXISTS proc_sql \  # 如果不存在则添加,否则不做操作

    CREATE PROCEDURE proc_sql (

        in strSQL char(128),

        in nidd int

    )

    BEGIN

            set @sqll = strSQL;

        set @p1 = nidd;

        PREPARE prod FROM @sqll;

        EXECUTE prod USING @p1;

        DEALLOCATE prepare prod;

    END\

    delimiter ;

    call proc_sql('select * from suoning2 where id > ?','2');

  • 相关阅读:
    关于JSON可能出现的错误,待更/todo
    mongoose的安装与使用(书签记录) 2017
    HTTP的学习记录3--HTTPS和HTTP
    HTTP的学习记录(二)头部
    HTTP(一)概述
    LeetCode 455. Assign Cookies
    LeetCode 453. Minimum Moves to Equal Array Elements
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode 447. Number of Boomerangs
    LeetCode 416. Partition Equal Subset Sum
  • 原文地址:https://www.cnblogs.com/yingjie2222/p/6084268.html
Copyright © 2011-2022 走看看