zoukankan      html  css  js  c++  java
  • MySQL进阶知识

    视图

    概念:给某个查询语句设置别名,创建这个别名的过程就叫创建视图,这个别名就是视图;注意:视图其实就是给一个select创建别名,在调用的时候才会生效,所以如果源数据内容更改,则视图内容同样会跟着改变

    创建格式
        create view 视图名称 as SQL;
    
    修改视图
        alter view 视图名称 as 新SQL;
    
    删除视图
        drop view 视图名称;
    
    例如:
      create view v1
    as select * from student where sid > 10;

    触发器

    概念:SQL触发器,是一种特殊类型的存储过程,不由用户直接调用。它在指定的表中的数据发生变化时自动生效。唤醒调用触发器以响应 INSERT、UPDATE 或 DELETE 语句。将触发器和触发它的语句作为可在触发器内回滚的单个事务对待。如果检测到严重错误(例如,磁盘空间不足),则整个事务即自动回滚。常常用于强制业务规则和数据完整性。

    创建格式
    delimiter //
    # 更改断句符
    create trigger 触发器名称 BEFORE INSERT on 表名 for EACH ROW
    # trigger 后面跟触发器名字,表名是告知触发器要在那个表的内容有变动之前做操作,EACH ROW是数据变动一行就触发一次触发器
    BEGIN
        INSERT into teacher(tname) values(NEW.sname);
    END //
    # 还原断句符
    delimiter ;
    创建数据之前触动触发器
    create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;
    create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;
    delimiter \
    create trigger tt1 BEFORE INSERT on t1 for EACH ROW
    BEGIN
      insert into t2(py) values(NEW.name);
    END \
    delimiter ;
    insert into t1(name) values('梁晓');
    创建数据之后触动触发器
    create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;
    create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;
    delimiter \
    create trigger tt2 AFTER INSERT on t1 for EACH ROW
    BEGIN
        insert into t2(py) values(NEW.name);
    END \
    delimiter ;
    insert into t1(name) values('王文杰');
    删除数据之前触动触发器
    create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;
    create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;
    delimiter \
    create trigger tt2 BEFORE DELETE on t1 for EACH ROW
    BEGIN
        insert into t2(py) values(NEW.name);
    END \
    delimiter ;
    insert into t1(name) values('王文杰');
    删除数据之后触动触发器
    create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;
    create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;
    delimiter \
    create trigger tt2 AFTER DELETE on t1 for EACH ROW
    BEGIN
        insert into t2(py) values(OLD.name);
    END \
    delimiter ;
    insert into t1(name) values('王文杰');
    更新数据之前触动触发器
    create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;
    create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;
    delimiter \
    create trigger tt2 BEFORE UPDATE on t1 for EACH ROW
    BEGIN
        insert into t2(py) values(NEW.name);
    END \
    delimiter ;
    insert into t1(name) values('王文杰');
    更新数据之后触动触发器
    create table t1(id int auto_increment key,name varchar(10) not null)engine=innodb;
    create table t2(id int auto_increment key,py varchar(10) not null)engine=innodb;
    delimiter \
    create trigger tt2 AFTER UPDATE on t1 for EACH ROW
    BEGIN
        insert into t2(py) values(OLD.name);
    END \
    delimiter ;
    insert into t1(name) values('王文杰');

    注意:这里的NEW代表的是新数据,OLD代表的是旧数据

    函数

    内置函数

    mysql中有内置函数,也可以自定义函数,函数用来完成用户的一些特定功能;下面附关于内置函数的教程地址。

    https://dev.mysql.com/doc/refman/5.7/en/functions.html(官方地址)
    https://www.runoob.com/mysql/mysql-functions.html     (中文教程)

    函数的使用格式

    select Function();
    # Function是函数名,函数名后面可以不跟载体,直接加入参数或者不加

    有一个比较要注意的内置date_format,下面附关于这个内置函数的一些相关参数:

    %a    Abbreviated weekday name (Sun..Sat)
    %b    Abbreviated month name (Jan..Dec)
    %c    Month, numeric (0..12)
    %D    Day of the month with English suffix (0th, 1st, 2nd, 3rd, …)
    %d    Day of the month, numeric (00..31)
    %e    Day of the month, numeric (0..31)
    %f    Microseconds (000000..999999)
    %H    Hour (00..23)
    %h    Hour (01..12)
    %I    Hour (01..12)
    %i    Minutes, numeric (00..59)
    %j    Day of year (001..366)
    %k    Hour (0..23)
    %l    Hour (1..12)
    %M    Month name (January..December)
    %m    Month, numeric (00..12)
    %p    AM or PM
    %r    Time, 12-hour (hh:mm:ss followed by AM or PM)
    %S    Seconds (00..59)
    %s    Seconds (00..59)
    %T    Time, 24-hour (hh:mm:ss)
    %U    Week (00..53), where Sunday is the first day of the week; WEEK() mode 0
    %u    Week (00..53), where Monday is the first day of the week; WEEK() mode 1
    %V    Week (01..53), where Sunday is the first day of the week; WEEK() mode 2; used with %X
    %v    Week (01..53), where Monday is the first day of the week; WEEK() mode 3; used with %x
    %W    Weekday name (Sunday..Saturday)
    %w    Day of the week (0=Sunday..6=Saturday)
    %X    Year for the week where Sunday is the first day of the week, numeric, four digits; used with %V
    %x    Year for the week, where Monday is the first day of the week, numeric, four digits; used with %v
    %Y    Year, numeric, four digits
    %y    Year, numeric (two digits)
    %%    A literal % character
    %x    x, for any “x” not listed above

    自定义函数

    创建自定义函数
    delimiter \
    # 更改换行符
    create function f1(
    # create function是固定格式,f1是函数名
        i1 int,
        # i1是参数,int是参数类型
        i2 int)
        # i2是参数,int是参数类型
    returns int
    # 设定返回值的数据类型,这个操作叫强定义
    BEGIN
        declare num int;
        # 声明一个变量名,并且声明这个变量名的类型
        set num = i1 + i2;
        # 设定函数要操作的具体内容,这里操作具体内容不能用mysql本身有的东西,比如select
        return(num);
        # 返回一个数据
    END \
    # 结束
    delimiter ;
    # 还原换行符
    删除自定义函数
    drop function f1;
    执行自定义函数
    select f1(11,22);
    # 在查询中执行函数

    存储过程

    概念:存储过程是一个SQL语句集合,当主动去调用存储过程时,其中内部的SQL语句会按照逻辑执行。

    存储过程的创建
    delimiter //
    create procedure p1()
    # create procedure 是固定格式 p1()是存储过程
    BEGIN
    # 设定开始标识
        select * from t1;
        # 存储过程需要执行的SQL语句
    END//
    # 设定结束标识
    delimiter ;
    
    call p1()
    # 执行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 ;
    
    set @t1 =4;
    # @变量名是用来创建mysql会话级的变量
    set @t2 = 0;
    CALL p1 (1, 2 ,@t1, @t2);
    SELECT @t1,@t2;
    # 这里@变量名也是用来调用会话级的变量

    事物

    事物用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。事物需要借助存储过程来进行完成

    事物的执行性能并不高

    示例

    delimiter \
    create PROCEDURE p1(
        OUT p_return_code tinyint
    # 定义一个存储过程,并且让这个存储过程返回一个值,以便程序调用
    )
    
    BEGIN
      DECLARE exit handler for sqlexception
      # 如果监测到事物执行异常,则执行下面的两个代码
      BEGIN
        -- ERROR
        set p_return_code = 1;
        # 设置p_return_code的返回值是1
        rollback;
        # 事物回滚
      END;
    
      DECLARE exit handler for sqlwarning
      # 如果事物执行成功一部分,则执行下面的内容
      BEGIN
        -- WARNING
        set p_return_code = 2;
        # 设置p_return_code的返回值是2
        rollback;
        # 回滚
      END;
    
      START TRANSACTION;
      # 开始执行事物
        DELETE from tb1;
        # 事物内容第一行
        insert into tb2(name)values('seven');
        # 事物内容第二行
      COMMIT;
      # 提交
    
      -- SUCCESS
      set p_return_code = 0;
      # 如果上面的事物执行成功,则设置p_return_code的返回值0
      END\
    delimiter ;

    动态执行SQL(防SQL注入)

    BEGIN
        #Routine body goes here...
       
      /*SQL语句变量*/
      DECLARE vstrSql VARCHAR(3000) DEFAULT ''; 
      /*映射表字段*/
      DECLARE vSourceTableName VARCHAR(50);
      DECLARE vSourceIdFieldName VARCHAR(50);
      DECLARE vSourceNameFieldName VARCHAR(50);
      DECLARE vTargetTableName VARCHAR(50);
      DECLARE vTargetIdFieldName VARCHAR(50);
      DECLARE vTargetNameFieldName VARCHAR(50); 
    
      /*更新数据*/
      DECLARE vnewValue VARCHAR(100);
      DECLARE vSourceIdFieldValue VARCHAR(100);
    
      DECLARE Done INT DEFAULT 0;
      /*声明游标*/
      DECLARE curRow CURSOR FOR 
      SELECT SourceTableName,SourceIdFieldName,SourceNameFieldName,TargetTableName,TargetIdFieldName,TargetNameFieldName
      FROM db_redundancy.TableFieldMap;
      /*设置终止标记*/
      DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET Done = 1;
      /*打开游标*/
      OPEN curRow;
        /*循环取出数据*/
        FETCH NEXT FROM curRow INTO vSourceTableName,vSourceIdFieldName,vSourceNameFieldName,vTargetTableName,vTargetIdFieldName,vTargetNameFieldName;
        WHILE Done<>1 DO
           #获取需要更新的数据
           SELECT SourceNameFieldNewValue,SourceIdFieldValue INTO vnewValue,vSourceIdFieldValue FROM db_redundancy.TableFieldValueModifyLog 
           WHERE  IsProcess=0 AND SourceTableName=vSourceTableName AND SourceIdFieldName=vSourceIdFieldName AND SourceNameFieldName=vSourceNameFieldName
           ORDER BY CreateDate DESC  limit 1;
           IF ISNULL(vnewValue) <> NULL || LENGTH(trim(vnewValue))>1 THEN
             #拼接语句
             SET vstrSql=CONCAT(' UPDATE ',vTargetTableName,' SET ', vTargetNameFieldName ,' = "',vnewValue,'" WHERE ', vTargetIdFieldName ,' = ', vSourceIdFieldValue,';');
             #注意很重要,将连成成的字符串赋值给一个变量(可以之前没有定义,但要以@开头SET @vSql= vstrSql;
             #预处理需要执行的动态SQL,其中stmt是一个变量
             PREPARE stmt  FROM @vSql;
             #执行语句
             EXECUTE stmt ;
             #释放语句
             DEALLOCATE PREPARE  stmt;
             #更新历史表中状态标记
             UPDATE db_redundancy.TableFieldValueModifyLog SET IsProcess=1 WHERE IsProcess=0 AND SourceTableName=vSourceTableName AND SourceIdFieldName=vSourceIdFieldName AND SourceIdFieldValue=vSourceIdFieldValue;
           END IF;
           #重置数据
           SET vnewValue='';
           SET vstrSql='';
          FETCH NEXT FROM curRow INTO vSourceTableName,vSourceIdFieldName,vSourceNameFieldName,vTargetTableName,vTargetIdFieldName,vTargetNameFieldName;
        END WHILE;
      /*关闭游标*/
      CLOSE curRow;
    END

    注意:防SQL注入可以在程序级别操作,也可以在SQL语句中做限制

    索引

    索引是一种数据加速查找的结构文件,需要使用者通过相关的SQL语句进行创建
    索引概念
    加速查找及部分约束
    功能描述
    主键索引:加速查找,且内容不能为空、不能重复
    普通索引:加速查找
    唯一索引:加速查找,且不能重复
    组合索引:多列组合成一个索引,功能可以参考上面的索引内容,组合的方式有如下几种
        组合主键索引
        组合唯一索引
        组合普通索引
    功能分类
    hash索引与btree索引,默认使用btree索引
    索引种类
    查询快、插入/更新慢、加速查找需要命中索引内容才可以
    索引特点
    组合索引:特点是最左前缀匹配,组合索引效率大于索引合并
    覆盖索引:在索引文件中直接获取数据,这种方式其实也没有多少加速效果
    索引合并:把多个单列索引合并使用,特点是方便一个表中有多列需要加速,不足是联合索引速度不如组合索引
    名词介绍
    数据库表中添加索引后确实会让查询速度起飞,但前提必须是正确的使用索引来查询,如果以错误的方式使用,则即使建立索引也会不奏效。即使建立索引,索引也不会生效,索引的命中规则如下:
    - like '%xx'(尽量不要用like匹配)
        select * from tb1 where name like '%cn';
    - 使用函数(不要用函数)
        select * from tb1 where reverse(name) = 'wupeiqi';
    - or
        select * from tb1 where nid = 1 or email = 'seven@live.com';
        特别的:当or条件中有未建立索引的列才失效,以下会走索引
                select * from tb1 where nid = 1 or name = 'seven';
                select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'
    - 类型不一致
        如果列是字符串类型,传入条件是必须用引号引起来,不然...
        select * from tb1 where name = 999;
    - !=
        select * from tb1 where name != 'alex'
        特别的:如果是主键,则还是会走索引
            select * from tb1 where nid != 123
    - >
        select * from tb1 where name > 'alex'
        特别的:如果是主键或索引是整数类型,则还是会走索引
            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                -- 不使用索引
    注意事项:
        - 避免使用select *
        - count(1)或count(列) 代替 count(*)
        - 创建表时尽量时 char 代替 varchar
        - 表的字段顺序固定长度的字段优先
        - 组合索引代替多个单列索引(经常使用多个条件查询时)
        - 尽量使用短索引
        - 使用连接(JOIN)来代替子查询(Sub-Queries)
        - 连表时注意条件类型需一致
        - 索引散列值(重复少)不适合建索引,例:性别不适合
    索引命中
    # 作用:加速查询
    # 单独创建:create index index_name on table_name(column_name)
    # 删除格式:drop index_name on table_name;
    # 查看索引:show index from table_name;
    # 连表创建:
    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)
    )
    
    注意:对于创建索引时如果是BLOB 和 TEXT 类型,必须指定length。
    普通索引
    # 作用:加速查询 和 唯一约束(可含null)
    # 单独格式:create unique index 索引名 on 表名(列名)
    # 删除格式:drop unique index 索引名 on 表名
    # 连表创建:
    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)
    )
    唯一索引
    # 作用:加速查询 和 唯一约束(不可含null)
    # 定义格式:alter table 表名 add primary key(列名);
    # 删除格式1:alter table 表名 drop primary key;
    # 删除格式2:alter table 表名  modify  列名 int, drop primary key;
    
    # 创建表 + 创建主键
    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 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)
    )
    主键索引
    # 作用:将n个列组合成一个索引
    # 应用场景:频繁的同时使用n列来进行查询,如:where n1 = 'alex' and n2 = 666。
    
    # 创建表
    create table in3(
        nid int not null auto_increment primary key,
        name varchar(32) not null,
        email varchar(64) not null,
        extra text
    )
    
    # 创建组合索引
    create index ix_name_email on in3(name,email);
    
    注意:对于同时搜索n个条件时,组合索引的性能好于多个单一索引合并。
    
    # 如上创建组合索引之后,查询:
    name and email  -- 使用索引
    name            -- 使用索引
    email           -- 不使用索引
    组合索引
  • 相关阅读:
    高阶篇:1.2)材料和工艺的选择
    高阶篇:4.1.1)QFDI(客户需求转换为设计要求)
    高阶篇:4)可靠性设计-总章
    高阶篇:1.5)如何选择更好的概念-Pugh矩阵法
    知识点篇:2)产品结构设计目标的分类
    高阶篇:1.1)竞品(标杆产品)的拆解和分析benchmarking
    支持向量机
    机器学习概述
    HDU_oj_2055 An easy problem
    HDU_oj_2054 A==B ?
  • 原文地址:https://www.cnblogs.com/guge-94/p/10841199.html
Copyright © 2011-2022 走看看