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

MySQL要点复习笔记

2020-04-06 16:47 92 查看

WITH ROLLUP 可以实现在分组统计数据基础上再进行一次统计(SUM,AVG,COUNT…)
        coalesce(a,b,c)    参数说明:如果a==null,则选择b;如果b==null,则选择c;如果a!=null,则选择a;如果a b c 都为null ,则返回为null(没意义)
        NULL值运算比较特殊,
            比较运算时不能使用=null或!=null,必须使用 IS NULL 和 IS NOT NULL
            算术运算时需进行判断转换ifnull(column,0)
        **事务:
            只有使用了Innodb数据库引擎的数据库才支持事务,事务处理用来保证数据库的完整性,保证成批的SQL要么全部执行,要么全部不执行
            事务必须满足4个条件:
                原子性:一个事务中的所有操作,要么全部执行,要么全部不执行,不会结束在中间某个环节。事务在执行过程中如果发生错误,会被全部回滚到开始前的状态
                一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏
                隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)
                持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
        修改MySQL默认字符集        windows下修改my.ini  linux下修改my.conf
            [client] 
            default-character-set=utf8mb4 
            
            [mysqld] 
            character-set-server = utf8mb4 
            collation-server = utf8mb4_unicode_ci 
            init_connect='SET NAMES utf8mb4'
            skip-character-set-client-handshake = true 
              
            [mysql] 
            default-character-set = utf8mb4
        
        error:
            [HY000][1366] Incorrect string value: '\xF0\x9F\x98\x81' for column 'name' at row 1
            表示编码字符集不能识别相应字符,例如enjoy表情
            解决方式
                ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
                alter table TABLE_NAME convert to character set utf8mb4 collate utf8mb4_bin; 
        设置序列的开始值:
            ALTER TABLE t AUTO_INCREMENT = 100;
        SQL注入:
            
        **主从复制
        
        **读写分离
        
        数据备份(导入导出)
            导出:
            select ... into outfile '/dir/data.sql'
                会有报错:The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
                解决方式:
                    配置文件添加末尾添加secure-file-priv=路径名,路径不加引号
                    然后重启,导出目标路径需为secure-file-priv
                    查询全局配置文件中配置信息:SELECT @@global.secure_file_priv;
            
            mysqldump    脚本程序,用于数据导出
            
            导入:
            mysql -u用户名    -p密码    <  要导入的数据库数据文件(runoob.sql)
            source /dir/data.sql
            LOAD DATA INFILE 'dump.txt' INTO TABLE mytbl;
            mysqlimport -u root -p --local mytbl dump.txt
        
        判断某个数据库中是否存在某个表
        select table_name from information_schema.TABLES where TABLE_SCHEMA = 'test' and TABLE_NAME = 'book';
        
        设置记录更新时间字段
            alter table book add update_time timestamp null on update current_timestamp;
        在MySQL5.5版本中单表不能同时存在两个字段为TIMESTAMP类型,若要设置记录创建时间字段,可以考虑使用触发器:
            报错: there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
            
            delimiter $$
            drop trigger if exists tri_book_create_time;
            create trigger tri_book_create_time
                before insert
                on book
                for each row
            begin
                if NEW.create_time is null
                then
                    set NEW.create_time = now();
                end if;
            end;
            $$
            delimiter ;
            
        
        
        replace into 语法
            replace into book(id, name, brief_introduction, number) values (8, '新版程序员进阶攻略(第4版)', '华夏出版社', 1000);
            
            MySQL中replace语句具体算法如下:
            1. 尝试把新行插入到表中
            2. 当因为主键(PRIMARY KEY)冲突错误或(UNIQUE INDEX)唯一索引重复错误而造成插入失败时:
            a. 从表中删除含有重复关键字值的冲突行
            b. 再次尝试把新行插入到表中
            
            replace语句会返回一个数,来指示受影响的行的数目。该数是被删除和被插入的行数的和。
            
        MySQL的@与@@区别

        @x 是 用户自定义的变量  (User variables are written as @var_name)

        @@x 是 global或session变量  (@@global  @@session )
            
        
            
        ***视图
        
        函数示例:
        -- 生成指定长度的字符串
        create function RANDOM_STR(len int)
            returns varchar(255)
        begin
            DECLARE chars_str VARCHAR(100) DEFAULT '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
            declare str varchar(255) default '';
            declare i int default 0;
            while i < len do
                set str = concat(str, SUBSTRING(chars_str, FLOOR(1+RAND()*52),1));
                set i = i + 1;
            end while;
            return str;
        end;
        -- 生成指定范围内的整数
        create function RANDOM_NUMBER(start int, end int)
            returns int
        begin
            DECLARE number int default 0;
            set number = floor(rand() * (end - start) + start);
            return number;
        end;
        
        **存储过程
            存储过程是一组为了完成特定功能的SQL语句的集合,使用存储过程的目的是将常用或复杂的工作预先SQL语句写好并用一个指定名称存储起来,
            这个过程经编译和优化后存储在数据库服务器中,因此称为存储过程。
            常用操作数据库的SQL语句在执行时需要先编译后执行,存储过程是预先编译并进行优化后存储在数据库服务器中。
            一个存储过程是一个可编程的函数,它在数据库中创建并保存,一般由SQL语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的特定功能时,存储过程尤为适合。
            1) 封装性
            存储过程被创建后,可以在程序中被多次调用,而不必重新编写该存储过程的 SQL 语句,并且数据库专业人员可以随时对存储过程进行修改,而不会影响到调用它的应用程序源代码。
            2) 可增强 SQL 语句的功能和灵活性
            存储过程可以用流程控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。
            3) 可减少网络流量
            由于存储过程是在服务器端运行的,且执行速度快,因此当客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而可降低网络负载。
            4) 高性能
            存储过程执行一次后,产生的二进制代码就驻留在缓冲区,在以后的调用中,只需要从缓冲区中执行二进制代码即可,从而提高了系统的效率和性能。
            5) 提高数据库的安全性和数据的完整性
            使用存储过程可以完成所有数据库操作,并且可以通过编程的方式控制数据库信息访问的权限。
        
        示例:
            -- 向一个测试表中插入数据100万条
            delimiter $$
            DROP procedure IF EXISTS mock_data;
            CREATE procedure mock_data()
            BEGIN
            DECLARE count INT DEFAULT 1000000;
            DECLARE i INT DEFAULT 0;
            WHILE i < count DO
                INSERT INTO app_user(`name`, `email`, `phone`, `gender`, `password`, `age`)
                VALUES(CONCAT('用户', i),
                       CONCAT(RANDOM_STR(10), '@163.com'),
                       CONCAT('18', RANDOM_NUMBER(100000000, 999999999)),
                       RANDOM_NUMBER(0,2), UUID(), RANDOM_NUMBER(0,100));
                SET i = i + 1;
            END WHILE;
            END
            $$
            delimiter ;
        
        **触发器
            一般应用场景:
                1. 新增记录时,对某些字段数据进行校验
                2. 删除记录时,一并删除相关联表中的对应数据,从而保持多个关联表之间数据的一致性。
                3. 每当删除一条数据时,在数据库存档表中保留一个备份副本
            
            优点:
                1. 根据某些事件触发,自动执行
                2. 可以通过数据库中相关的表层叠修改另外的表
                3. 可以实施比Foreign Key和Check约束更为复杂的检查和操作
                
            在 MySQL 中,只有执行 INSERT、UPDATE 和 DELETE 操作时才能激活触发器
            注意:每个表都支持 INSERT、UPDATE 和 DELETE 的 BEFORE 与 AFTER,因此每个表最多支持 6 个触发器。
                  每个表的每个事件每次只允许有一个触发器。单一触发器不能与多个事件或多个表关联。
                  
            语法格式:
                CREATE <触发器名> < BEFORE | AFTER >
                <INSERT | UPDATE | DELETE >
                ON <表名> FOR EACH Row<触发器主体>
                
                eg:
                    delimiter $$
                    drop trigger if exists tri_book_create_time;
                    create trigger tri_book_create_time
                        before insert
                        on book
                        for each row
                    begin
                        if NEW.create_time is null
                        then
                            set NEW.create_time = now();
                        end if;
                    end;
                    $$
                    delimiter ;
            使用INSERT触发器注意点:
                在INSERT触发器代码内,可引用一个名为NEW的虚拟表来访问被插入的行
                在BEFORE INSERT触发器中,NEW中的值也可以被更新,即允许更改被插入的值
                对于AUTO_INCREMENT 列,NEW 在 INSERT 执行之前是0,在 INSERT 执行之后为自动生成的值
            使用 UPDATE 触发器注意点:
                同样可以在触发器代码内使用 NEW 来访问更新的值
                有一个 OLD 虚拟表来访问 UODATE 语句执行之前的值
                在 BREFORE UPDATE触发器中, NEW 中的值可能也被更新,即允许更改将要用于 UPDATE 语句中的值
                OLD 中的值是只读的,不能被更新
            使用 DELELTE 触发器注意点:
                在触发器代码,可以引用 OLD 虚拟表来访问被删除的行
                OLD 中的值是只读的,不能被更新
            报错处置:
                若对于事务性表,如果触发程序失败,以及由此导致的整个语句失败,那么该语句所执行的所有操作都要被回滚;
                对于非事务性表,不能执行此类回滚,即使语句失败,已进行的修改依然有效
                若 BEFORE 触发程序失败,则 MYSQL 将不执行相应行上的操作
                若在 BEFORE 和 AFERT 触发程序的执行过程中出现错误,则将导致调用触发程序的整个语句失败
                仅当 BEFORE 触发程序和行操作均已被成功执行,MySQL 才会执行 AFTER 触发程序
            
            ***索引
                索引是数据库性能调优技术的基础,常用于实现数据的快速检索
                索引就是根据表中的一列或若干列按照一定顺序建立的列值与记录行之间的对应关系,实质上是一张描述索引列的列值和原表中记录行之间一一对应关系的有序表
                
                索引大致分为:普通索引,唯一索引,主键索引,空间索引,全文索引
                    1. 每个表只能有一个主键索引
                    2. 全文索引只能在 VARCHAR 和 TEXT 类型的列上创建,并且只能在 MyISAM 表中创建
                
                恰当的使用索引可以加快数据检索的性能,但过多的使用索引也会造成一些弊端:
                    1. 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加
                    2. 除了数据表占数据空间之外,每一个索引还要占用一定的物理空间。如果要建立聚簇索引,那么需要的空间就会更大
                    3. 在进行增删改操作时,索引也要动态维护,会降低了数据的维护速度
                    
                建立索引应遵循的原则:
                    1. 在经常需要搜索的列上建立索引
                    2. 在做为主键的列上创建索引,强制该列的唯一性
                    3. 在经常使用的表连接的列上创建索引,这些列主要是一些外键,可以加快表连接的速度
                    4. 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,所以其指定的范围是连续
                    5. 在经常需要排序的列上创建索引,因为索引已经排序,所以查询时可以利用索引的排序,加快排序查询
                    6. 在经常使用 WHERE 子句的列上创建索引,加快条件判断的速度
                一般来说不适合创建索引的场景:
                    1. 对于查询中很少使用或参考的列不应该创建索引
                    2. 对于那些只有很少数据值的列也不应该创建索引,例如人的性别
                    3. 对于那些定义为 TEXT、IMAGE 和 BIT 数据类型的列不应该创建索引,因为这些列的数量要么相当大,要么取值很少
                    4. 当修改性能远远大于检索性能时,不应该创建索引,否则会进一步降低修改性能
                    
            行锁、表锁
            
            
            用户管理
                新建用户:create user phw identified by 'phw123';
                重命名用户名:rename user phw to panhongwei;
                修改用户密码:set password for panhongwei = password('123123');
                删除用户:drop user panhongwei;
                授权:grant all privileges on test.* to phw;
                取消授权:revoke insert,update on test.* from phw;
                每次权限更新后要使用:flush privileges;    进行刷新
                禁止root用户在远程机器上访问mysql:delete from user where user="root" and host="%" ;
                设置root可以远程登录GRANT ALL PRIVILEGES ON *.* TO root@"%" IDENTIFIED BY '123456' WITH GRANT OPTION;
            
            mysqlslap:MySQL 5.1版本后自带的性能测试工具
            
            sql_mode:
            
            预处理语句示例
                prepare stmt from '';
                EXECUTE stmt;
                DEALLOCATE PREPARE stmt;
            
            函数和存储过程的区别?
            timestamp和datetime的区别?
            mysql的事务和锁机制如何进行的?
            
            索引优化:
                1.    数据达到巨大量级时,适合建索引。
                2.    经常被where、order by、group by、join、selelct的列建索引
                3.    多列索引遵循最佳左前缀标准,条件筛选列设置的筛选字段顺序符合多列索引字段顺序
                4.    对索引列进行计算、使用函数会导致索引失效
                5.    like查询以'%'开始而且查询字段未全部在索引列中,会导致索引失效
                6.    没有遵循最佳左前缀原则,设置字段顺序,会导致索引失效
                7.    表本身数据比较大,where条件筛选后数据太多,大于15%,会导致索引失效(CBO计算走索引花费的时间大于走全表)
                8.    类型错误,索引字段本身是varchar类型,where设置时使用了number
                9.    **覆盖索引(定义:如果一个索引包含(或覆盖)所有需要查询的字段的值,称为‘覆盖索引’。即只需扫描索引而无须回表),select 后的查询字段全部在索引中
                10.    where条件查询中含有or关键字,索引失效,尽量使用union all改造sql语句

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