zoukankan      html  css  js  c++  java
  • 关系型数据库_mysql

      MySQL是最流行的关系型数据库管理系统,那么问题来了:什么是关系型数据库呢?还有其他类型数据库嘛?

    一、数据库类型

       关系型数据库:数据结构是表,由二维表及其之间的联系组成的数据组织(MySQL、SQLServer)

    优点:
        (1)易于维护:都是使用表结构,格式统一;
        (2)使用方便:SQL语言通用,可用于复杂查询;
        (3)复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询
    缺点:
        (1)读写性能比较差,尤其是海量数据的高效率读写;
        (2)固定的结构,灵活差;
        (3)高并发读写需求,关系型数据库对硬盘I/O是很大的瓶颈
    

       非关系型数据库:严格上不是一种数据库,而是一种数据结构化存储方法的集合,也可以是文档或键值对等(Redis、MongoDB)

    优点:
        (1)格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式
        (2)速度快:可以使用硬盘或随机存储器作为载体,关系型只能使用硬盘
        (3)高扩展性
        (4)成本低:数据库部署简单,基本都是开源的
    缺点:
        (1)不提供SQL支持,学习和使用成本较高
        (2)无事务处理
        (3)数据结构相对复杂,复杂查询性能
    

    二、 mysql环境配置

      老生常谈,工欲善其事必先利其器!相对于windows系列的下一步下一步的安装,我们着重看下Ubuntu环境下的MySQL安装与配置踩过的坑吧。

    1.卸载mysql

      为什么要先卸载呢?你能找到这篇文章,可能此刻的你已经在焦虑安装MySQL为什么老不成功呢,那么先按下面卸载掉它;如果你是第一次安装MySQL的话,请忽略这一步的操作。

    # 先更新下Ubuntu的软件
    sudo apt-get update
    
    # 删除 mysql-server
    sudo apt-get remove mysql-server
    # 删除和mysql相关的服务
    sudo apt-get autoremove mysql-server
    # 删除 mysql-common
    sudo apt-get remove mmysql-common
    # 清除残留数据
    dpkg -l | grep ^rc | awk '{print $2}' | sudo xargs dpkg -P
    

    2.安装mysql

    # 坑就在这里,记得之前安装的时候是会让输入用户名和密码的,但不知道怎滴就没了
    sudo apt-get install mysql-server
    sudo apt-get install mysql-client
    sudo apt-get install libmysqlclient-dev
    
    # 查看MySQL服务是否安装成功
    sudo netstat -tap | grep mysql
    

    3.修改mysql配置文件

    sudo vi /etc/mysql/mysql.conf.d
    
    '
    # 将 bind-address=127.0.0.1 修改为 bind-address=0.0.0.0
    # 也可以改成你指定终端的IP地址
    bind-address=0.0.0.0
    '
    # 启动MySQL服务
    sudo /etc/init.d/mysql restart
    
    # 重启MySQL服务
    sudo /etc/init.d/mysql restart
    

    4.命令行操作数据库

    $ sudo mysql -u root -p
    Enter password: 
    # 直接就按Enter键就行了,因为在安装mysql-server的时候没有设置用户名和密码;虽然也可以操作数据库但是操作起来非常的不方便。
    
    # 如果在数据库连接工具中连接该数据库就会报错:ERROR 1698 (28000): Access denied for user 'root'@'localhost'
    
    mysql> USE mysql;
    mysql> SELECT user, plugin FROM mysql.user;
    # 查询结果
    +------------------+-----------------------+
    | user             | plugin                |
    +------------------+-----------------------+
    | root             | mauth_socket          |
    | mysql.session    | mysql_native_password |
    | mysql.sys        | mysql_native_password |
    | debian-sys-maint | mysql_native_password |
    | root             | mysql_native_password |
    +------------------+-----------------------+
    5 rows in set (0.00 sec)
    # 结果发现root的plugin='auth_socket'并不是本地密码,因此需要修改它
    
    # 修改root账户的密码和plugin的本地密码验证方式
    mysql> UPDATE mysql.user SET authentication_string=PASSWORD('123'), plugin='mysql_native_password' WHERE user='root';
    
    # 刷新
    mysql> FLUSH PRIVILEGES;
    
    # 退出
    mysql> exit;
    
    # 用再次登录的时候就输入用户名密码就可以登录成功了
    

    5.命令行操作数据库

    mysql> SET GLOBAL validate_password_policy=0;
    mysql> SET GLOBAL validate_password_mixed_case_count=0;
    mysql> SET GLOBAL validate_password_number_count=3;
    mysql> SET GLOBAL validate_password_special_char_count=0;
    mysql> SET GLOBAL validate_password_length=3;
    mysql> UPDATE mysql.user SET authentication_string=PASSWORD('123'), plugin='mysql_native_password' WHERE user='root';
    mysql> FLUSH PRIVILEGES;
    mysql> exit;
    

    6.访问数据库

    -- 解决密码问题:https://blog.csdn.net/qq_32799165/article/details/83574665
    --   mysql -u root -h 127.0.0.1 -p
    GRANT ALL PRIVILEGES ON *.* TO 'root'@''IDENTIFIED BY 'rootpassword' WITH GRANT OPTION;
    FLUSH PRIVILEGES;
    

    7.授权管理

    -- 用户管理特殊命令(PS:用户权限相关数据保存在mysql书库的user表中,不建议直接对其操作)
    --   创建用户
               CREATE USER '用户名'@'IP地址' IDENTIFIED BY '密码';
    --   删除用户
               DROP USER '用户名'@'IP地址';
    --   修改用户
               RENAME USER '用户名'@'IP地址' TO '新用户名'@'新IP地址';
    --   修改密码
               SET PASSWORD FOR '用户名'@'IP地址' = PASSWORD('新密码');
    --
    -- 用户权限管理(默认权限什么都没有)
    --   查看权限
               SHOW GRANTS FOR '用户名'@'IP地址';
    --   授权
    --   权限[      ALL PRIVILEGES  除grant外的所有权限
    --             SELECT          仅查权限
    --             SELECT,INSERT   查和插入权限
    --             ...
    --             USAGE                   无访问权限
    --             ALTER                   使用alter table
    --             ALTER ROUTINE           使用alter procedure和drop procedure
    --             CREATE                  使用create table
    --             CREATE ROUTINE          使用create procedure
    --             CREATE TEMPORARY TABLES 使用create temporary tables
    --             CREATE USER             使用create user、drop user、rename user和revoke  all privileges
    --             CREATE VIEW             使用create view
    --             DELETE                  使用delete
    --             DROP                    使用drop table
    --             EXECUTE                 使用call和存储过程
    --             FILE                    使用select into outfile 和 load data infile
    --             GRANT OPTION            使用grant 和 revoke
    --             INDEX                   使用index
    --             INSERT                  使用insert
    --             LOCK TABLES             使用lock table
    --             PROCESS                 使用show full processlist
    --             SHOW DATABASES          使用show databases
    --             SHOW VIEW               使用show view
    --             UPDATE                  使用update
    --             RELOAD                  使用flush
    --             SHUTDOWN                使用mysqladmin shutdown(关闭MySQL)
    --             SUPER                   使用change master、kill、logs、purge、master和set global。还允许mysqladmin调试登陆
    --             REPLICATION CLIENT      服务器位置的访问
    --             REPLICATION SLAVE       由复制从属使用
    -- ]
               GRANT INSERT(权限) ON '数据库'.'表' TO '用户'@'IP地址';
    --   取消权限
               REVOKE INSERT(权限) ON '数据库'.'表' FROM '用户'@'IP地址';
    -- [数据库.表:   数据库.*           (数据库中的所有表)、
    --              数据库.存储过程     (指定数据库中的存储过程)
    --              数据库.表          (指定数据库中的某张表)
    --              *.*               (所有数据库)
    -- ]
    
    -- ['用户名'@'IP地址'         (用户只能在该IP下才能访问)
    --  '用户名'@'192.168.1.%'    (用户只能在改IP段下才能访问(通配符%表示任意))
    --  '用户名'@'%'              (用户可以再任意IP下访问(默认IP地址为%))
    

    8.忘记密码

    -- 启动免授权服务端
    --       mysqld --skip-grant-tables
    -- 客户端
    --       mysql -u root -p
    -- 修改用户名和密码
          UPDATE mysql.user SET authentication_string=PASSWORD('password') WHERE user='root';
    -- FLUSH PRIVILEGES;
    

    三、数据库基本操作

    GitHub示例

    1.数据库操作

    -- 显示数据库
    SHOW DATABASES;
    
    -- 创建数据库
    -- utf-8 编码格式的数据库
    CREATE DATABASE databases_example DEFAULT CHARACTER  SET utf8 COLLATE utf8_croatian_ci;
    -- gbk的数据库
    CREATE DATABASE databases_example DEFAULT CHARACTER  SET gbk COLLATE gbk_chinese_ci;
    
    -- 使用数据库
    USE databases_example;
    

    2.数据库表

    -- 使用表
    USE databases_example;
    SHOW TABLES;
    
    -- 2.1 创建表
    USE databases_example;
    CREATE TABLE IF NOT EXISTS user_info(
        id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '自增列',  -- 设置为自增,插入数据时无需设置此列,默认将自增(表中只能有一个自增列)
        uid INT NOT NULL COMMENT '用户唯一的UID',  -- 主键不允许有空值,单列它的值必须唯一,如果是多列,则其组合必须唯一
        name VARCHAR(30) NOT NULL COMMENT '用户名',
        sex INT NOT NULL COMMENT '用户性别:0男;1女',    -- 不可以为空
        job VARCHAR(30) NULL COMMENT '用户职业',    -- 可以为空
        age VARCHAR(20) NOT NULL DEFAULT '请填写' COMMENT '用户年龄',   -- 创建列时添加默认值,未指定默认值自动添加默认值
        address TEXT NOT NULL COMMENT '通信地址',
        detail TEXT NULL COMMENT '备注'
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;
    USE databases_example;
    CREATE TABLE IF NOT EXISTS sex (
      sex_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '性别id',
      sex_name VARBINARY(10) NOT NULL COMMENT '实际性别'
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    -- 2.2 删除表
    -- TRUNCATE:快速清空数据表的全部数据,不会破坏表的结构
    TRUNCATE TABLE databases_example.user_info;
    -- DELETE:删除表的指定数据
    DELETE FROM databases_example.user_info WHERE id = '11';
    -- DROP:删除表,清空数据并会删除表的结构
    DROP TABLE databases_example.user_info;
    
    -- 2.3 修改表
    -- 添加列
    ALTER TABLE databases_example.user_info ADD add_col VARCHAR(20) COMMENT '表添加的列';
    ALTER TABLE databases_example.user_info ADD add_col2 VARCHAR(20) COMMENT '修改表添加的列';
    -- 删除列
    ALTER TABLE databases_example.user_info DROP COLUMN add_col2;
    -- 修改列信息
    ALTER TABLE databases_example.user_info MODIFY COLUMN add_col INT COMMENT '表修改的列';
    ALTER TABLE databases_example.user_info CHANGE COLUMN add_col2 change_col INT COMMENT '修改列名和该列的类型';
    -- 添加主键
    ALTER TABLE databases_example.user_info ADD PRIMARY KEY(add_col);
    -- 删除主键
    ALTER TABLE databases_example.user_info DROP PRIMARY KEY;
    ALTER TABLE databases_example.user_info MODIFY add_col INT, DROP PRIMARY KEY;
    -- 添加外键
    ALTER TABLE '从表' ADD constraint '外键名称_FK_从表_主表' FOREIGN KEY '从表'('外键字段') REFERENCES '主表'('主键字段');
    ALTER TABLE databases_example.user_info ADD constraint '外键名称_FK_从表_主表' FOREIGN KEY '从表'('外键字段') REFERENCES '主表'('主键字段');
    -- 删除外键
    ALTER TABLE databases_example.user_info DROP FOREIGN KEY '外键名称';
    -- 修改默认值
    ALTER TABLE databases_example.user_info ALTER add_col SET DEFAULT 1000;
    -- 删除默认值
    ALTER TABLE databases_example.user_info ALTER add_col DROP DEFAULT;
    

    3.数据类型

    -- 3. 数据类型
    -- bit
    -- int
    -- bigint
    -- decimal
    -- float
    -- double
    -- char
    -- varchar
    -- text
    -- mediumtext
    -- longtext
    -- enum
    -- set
    -- DATE
    -- TIME
    -- YEAR
    -- DATETIME
    -- TIMESTAMP
    

    四、数据库增删改查

    GitHub示例

    1.增加

    -- 基本语法:INSERT INTO table_name(clo1, clo2, ..., clon) VALUES(value1, value2, ..., valuen);
    INSERT INTO databases_example.user_info(uid, name, sex, job, age, address, detail, add_col, change_col)
    VALUES ('000011', '小A', 0, 'Programmer', 19, '北京朝阳酒仙桥', '喜欢睡觉', 20, 25),
           ('000012', '小B', 0, 'Programmer', 18, '北京朝阳酒仙桥', '喜欢睡觉', 20, 25),
           ('000013', '小B', 0, 'Programmer', 18, '北京朝阳酒仙桥', '喜欢睡觉', 20, 25);
    

    2.删除

    -- 基本语法:DELETE FROM table_name;
    DELETE FROM databases_example.user_info WHERE id=1;
    TRUNCATE TABLE databases_example.sex;
    DROP TABLE databases_example.sex;
    

    3.修改

    -- 基本语法:UPDATE table_name SET name='要修改内容' WHERE id=1;
    UPDATE databases_example.user_info SET name='AA' WHERE id=1;
    

    4.查询

    -- 基本语法:
    SELECT * FROM databases_example.user_info WHERE id>1;
    -- 【条件】
    SELECT * FROM databases_example.user_info WHERE id>1;
    SELECT * FROM databases_example.user_info WHERE id BETWEEN 2 AND 5;
    SELECT * FROM databases_example.user_info WHERE id IN(2, 4, 6);
    SELECT * FROM databases_example.user_info WHERE id NOT IN(2, 4, 6);
    SELECT * FROM databases_example.user_info WHERE id IN(SELECT uid FROM user_info );
    -- 【通配符】
    SELECT * FROM databases_example.user_info WHERE name LIKE '小%';  -- 开头的所有(多个字符串)
    SELECT * FROM databases_example.user_info WHERE name LIKE '小_';  -- ale开头的所有(一个字符)
    -- 【限制(分页)】
    SELECT * FROM databases_example.user_info LIMIT 3;                   -- 前三行
    SELECT * FROM databases_example.user_info LIMIT 4, 5;                -- 从第4行开始后的5行
    SELECT * FROM databases_example.user_info LIMIT 2 OFFSET 2;          -- 从第2行开始后的1行
    -- 【排序】
    SELECT * FROM databases_example.user_info ORDER BY id ASC;     -- 根据 “列” 从小到大排列
    SELECT * FROM databases_example.user_info ORDER BY id DESC;     -- 根据 “列” 从大到小排列
    SELECT * FROM databases_example.user_info ORDER BY id DESC, uid ASC;     -- 根据 “列1” 从大到小排列,如果相同则按列2从小到大排序
    -- 【分组】
    -- 特别的:group by 必须在where之后,order by之前
    SELECT id FROM databases_example.user_info WHERE id > 1 GROUP BY age;
    -- 【连表】
    -- 无对应关系则不显示
    SELECT A.id, A.name, B.sex_name FROM databases_example.user_info AS A, databases_example.sex AS B WHERE A.nid = B.nid;
    -- 无对应关系则不显示
    SELECT A.id, A.name, B.sex_name FROM databases_example.user_info AS A INNER JOIN databases_example.sex AS B ON A.id = B.sex_id;
    -- A表所有显示,如果B中无对应关系,则值为null
    SELECT A.id, A.name, B.sex_name FROM databases_example.user_info AS A LEFT JOIN databases_example.sex AS B ON A.id = B.sex_id;
    -- B表所有显示,如果B中无对应关系,则值为null
    SELECT A.id, A.name, B.sex_name FROM databases_example.user_info AS A RIGHT JOIN databases_example.sex AS B ON A.id = B.sex_id;
    -- 【组合】
    -- 组合,自动处理重合
    SELECT name FROM databases_example.user_info AS A UNION SELECT sex_name FROM databases_example.sex AS B;
    -- 组合,不处理重合
    SELECT name FROM databases_example.user_info AS A UNION ALL SELECT sex_name FROM databases_example.sex AS B;
    

    五、视图操作

      视图就是一张虚拟表(非真实存在),其本质是 sql 语句获取动态的数据集并为其命名,由于视图是虚拟表,无法对进行更新和删除,仅能做查询操作。【GitHub示例

    1.创建视图

    --  语法格式:CREATE VIEW '视图名称' AS 'SQL语句'
    CREATE VIEW user_id AS
        SELECT uid FROM databases_example.user_info;
    

    2.视图使用

    -- 由于视图是虚拟表,无法对进行更新和删除,仅能做查询操作
    SELECT * FROM databases_example.user_id;
    

    3.删除视图

    -- 语法格式:DROP VIEW '视图名称'
    DROP VIEW databases_example.user_id;
    

    4.修改视图

    -- 语法格式:ALTER VIEW '视图名称' AS 'SQL语句'
    ALTER VIEW databases_example.user_id AS
        SELECT * FROM databases_example.user_info;
    

    六、触发器

      对某个表进行【增/删/改】操作的前后如果希望出发某个特定的行为时,可以使用出发器;触发器用于定制用户对表进行【增/删/改】前后的行为。【GitHub示例

    1.创建触发器

    -- 格式:create trigger	触发器名	触发时间(BEFORE|AFTER)	触发事件	on 表名	for each now
    --      触发器触发的具体事务
    -- 执行过程为:执行触发事件作用在某个表上前或后,触发器执行具体的事物
    DELIMITER //
    CREATE TRIGGER tri_before_insert_user_info BEFORE INSERT ON databases_example.user_info FOR EACH ROW
        BEGIN
            SELECT COUNT(*) INTO @num;
        END //
    DELIMITER ;
    

    2.使用触发器

    INSERT INTO databases_example.user_info(uid, name, sex, job, age, address, detail, add_col, change_col)
                                     VALUES('000016', '小C', 0, 'Programmer', 18, '北京朝阳酒仙桥', '喜欢睡觉', 20, 25);
    SELECT * FROM databases_example.user_info;
    

    3.删除触发器

    DROP TRIGGER tri_before_insert_user_info;
    
    
    INSERT INTO databases_example.user_info(uid, name, sex, job, age, address, detail, add_col, change_col)
    VALUES('000015', '小B', 0, 'Programmer', 18, '北京朝阳酒仙桥', '喜欢睡觉', 20, 25);
    

    七、索引

      索引用于快速找出数据表中某一列中有一特定值的行。不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大查询的时间相应就越长。索引的建立就是快速达到一个位置去搜索数据文件,而不必查看所有数据,将会节省大量时间。

    优点:(1)MySQL列类型都可以设置索引并且被索引;
          (2)大大加快数据的查询速度
    缺点:(1)需要创建和维护耗费时间,随着数据量的增加所耗费的时间也会增加
          (2)索引也需要占空间,索引文件有可能比数据文件都会大
          (3)对表中数据进行增加、删除、修改时,索引也需要动态维护,降低了数据的维护速度。
    

    GitHub示例

    1. 普通索引

      普通索引仅有一个功能:加速查询

    -- 创建表的时候创建索引
    USE databases_example;
    CREATE TABLE index_table(
        nid INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
        name VARCHAR(20) NOT NULL ,
        email VARCHAR(30) NOT NULL ,
        -- 注意:对于创建索引时如果是 BLOB 和 TEXT 类型,必须指定length。
        -- create index ix_extra on in1(extra(32));
        INDEX ix_name(name)
    );
    -- 令一种创建索引的方式
    CREATE INDEX ix_nid ON index_table(nid);
    -- 删除索引
    DROP INDEX ix_name ON index_table;
    -- 查看创建的索引
    SHOW INDEX FROM databases_example.index_table;
    

    2. 唯一索引

      唯一索引有两个功能:加速查询 和 唯一约束(可含NULL);也就是说表中只有一个索引,说明一下自增键也是索引的一种。

    USE databases_example;
    CREATE TABLE unique_table(
        nid INT NOT NULL AUTO_INCREMENT ,
        name VARCHAR(20) NOT NULL ,
        email VARCHAR(20) NOT NULL ,
        extra TEXT ,
        UNIQUE ix_nid(nid)
    
    );
    -- 另一种创建唯一索引的方法
    CREATE UNIQUE INDEX ix_nid ON databases_example.unique_table(nid) ;
    -- 查看创建的唯一索引
    SHOW INDEX FROM databases_example.unique_table;
    -- 删除唯一索引
    DROP INDEX ix_name ON databases_example.unique_table;
    

    3. 主键索引

      主键索引有两个功能:加速查询 和 唯一约束(不可含null)。

    USE databases_example;
    CREATE TABLE primary_table(
        nid INT NOT NULL AUTO_INCREMENT ,
        name VARCHAR(20) NOT NULL ,
        email VARCHAR(30) NOT NULL ,
        PRIMARY KEY (nid) ,
        INDEX ix_nid(name)
    );
    -- 查看创建的主键索引
    SHOW INDEX FROM databases_example.primary_table;
    -- 另一种创建方法
    CREATE INDEX ix_name ON databases_example.primary_table(name);
    -- 删除主键索引
    ALTER TABLE databases_example.primary_table DROP PRIMARY KEY;
    ALTER TABLE databases_example.primary_table MODIFY INT, DROP PRIMARY KEY;
    

    4. 组合索引

      组合索引时将n个列组合成一个索引,其应用场景为:频繁的同事使用n列来进行查询,如:WHERE n1 = 'ALEX' AND n2 = 666。

    USE databases_example;
    CREATE TABLE mixture_table(
        nid INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
        name VARCHAR(20) NOT NULL ,
        email VARCHAR(20) NOT NULL
    );
    -- 创建索引
    CREATE INDEX ix_nid_name ON mixture_table(nid, name);
    -- 查看组合索引
    SHOW INDEX FROM mixture_table;
    -- 删除组合索引
    DROP INDEX ix_nid_name ON mixture_table;
    

    八、函数

    GitHub示例

    1.自定义函数

    DELIMITER //
    CREATE FUNCTION f1(
        i1 INT,
        i2 INT
    )
    RETURNS INT
    BEGIN
        DECLARE num INT;
        SET num = i1 + i2;
        RETURN(num);
    END //
    DELIMITER ;
    

    2.执行函数

    SELECT f1(2,3) AS add_result;
    

    3.删除函数

    DROP FUNCTION f1;
    

    九、语句控制

    GitHub示例

    1.条件语句

    1.1 if语句

    -- 1.1 if语句
    CREATE PROCEDURE pro_fi()
    BEGIN
        DECLARE i INT DEFAULT 0;
        IF i = 1 THEN
            SELECT i;
        ELSEIF i = 2 THEN
            SELECT 2;
        ELSE
            SELECT 22;
        END IF ;
    END ;
    CALL pro_fi();
    

    1.2 case语句

    -- 1.2 case语句
    SELECT CASE WHEN uid = 11 THEN 'A'
                WHEN uid = 12 THEN 'B'
                WHEN uid = 13 THEN 'C'
            ELSE 'X' END 
            AS 'test'
    FROM databases_example.user_info;
    

    2.循环语句

    2.1 while循环

    -- 2.1 while循环
    USE databases_example;
    DELIMITER //
    CREATE PROCEDURE pro_while()
    BEGIN
       DECLARE num INT;
       SET num = 0;
       WHILE num < 100 DO
           SELECT num;
           SET num = num + 20;
       END WHILE;
    END //
    DELIMITER ;
    CALL pro_while();
    

    2.2 repeat循环

    USE databases_example;
    DELIMITER //
    CREATE PROCEDURE pro_repeat()
    BEGIN
        DECLARE i INT;
        SET i=0;
        REPEAT
            SELECT i;
            SET i = i + 1;
        UNTIL i<= 5
        END REPEAT;
    END //
    DELIMITER ;
    CALL pro_repeat();
    

    2.3 loop循环

    USE databases_example;
    DELIMITER //
    CREATE PROCEDURE pro_loop()
    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;
    END ;
    DELIMITER ;
    CALL pro_loop();
    

    十、存储过程

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

    1. 创建存储过程

    -- 1.1 无参数存储过程
    DELIMITER //
    CREATE PROCEDURE pro_no_para()
    BEGIN
        SELECT * FROM databases_example.user_info;
    END //
    DELIMITER ;
    CALL pro_no_para();
    -- 1.2 有参数存储过程
    -- 对于存储过程可接受参数,其参数有三类:
    --     in     仅用于传入参数用
    --     out    仅用于返回值用
    --     inout  既可以传入又可以当作返回值
    DELIMITER //
    CREATE PROCEDURE pro_para(
        IN i1 INT,
        IN i2 INT,
        INOUT i3 INT,
        OUT o1 INT
    )
    BEGIN
        DECLARE temp1 INT;
        DECLARE temp2 INT DEFAULT 0;
    
        SET temp1 = 1;
        SET o1 = i1 + i2 + temp1 + temp2;
        SET i3 = i3 + 100;
    END //
    DELIMITER ;
    -- 执行有参数的存储过程(注意传参顺序传值的)
    SET @t1 = 4;
    SET @t2 = 5;
    CALL pro_para(1, 6, @t1, @t2);
    SELECT @t1, @t2;
    

    2. 结果集

    DELIMITER //
    CREATE PROCEDURE pr4(
      IN n1 INT,
      INOUT n3 INT,
      OUT n2 INT
    )
    BEGIN
      DECLARE temp1 INT;
      DECLARE temp2 INT DEFAULT 0;
    
      SELECT * FROM databases_example.user_info;
      SET n2 = n1 + 100;
      SET n3 = n3 + n1 +100;
    END //
    DELIMITER ;
    SET @t4 = 111;
    SET @t5 = 222;
    CALL pr4(100, @t4, @t5);
    SELECT @t4, @t5;
    

    3. 删除存储过程

    DROP PROCEDURE pro_no_para;
    

    十一、事务

      MySQL事务主要用于处理操作量大,复杂度高的数据。例如:在人员管理系统中删除一个人员,需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱、文章等,这些数据库操作语句就构成了一个事务。

    (1)原子性:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节;事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样
    (2)一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
    (3)隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
    (4)持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
    

    GitHub示例

    1. 创建事务

    -- 1.创建事务
    DELIMITER //
    CREATE PROCEDURE pro_transaction(
        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 ;
            INSERT INTO databases_example.user_info(uid, name, sex, job, age, address, detail, add_col, change_col)
                    VALUES('000015', '事务', 0, 'Programmer', 18, '北京朝阳酒仙桥', '喜欢睡觉', 20, 25);
        COMMIT ;
    
        -- success
        SET p_return_code = 0;
    END //
    DELIMITER ;
    

    2.执行事务

    -- 2.执行事务
    SET @i = 0;
    CALL pro_transaction(@i);
    SELECT @i;
    
    Be a simple myself!
  • 相关阅读:
    Vue 从入门到进阶之路(十四)
    Vue 从入门到进阶之路(十三)
    Vue 从入门到进阶之路(十二)
    Vue 从入门到进阶之路(十一)
    vue-cli 3.x 开发插件并发布到 npm
    2018 年终总结 & 2019 年度计划
    帝都夜话
    移动端实现拖拽的两种方法
    前端面试(原生js篇)
    在前端获取图片宽高
  • 原文地址:https://www.cnblogs.com/secoder/p/12901844.html
Copyright © 2011-2022 走看看