• 存储过程


    1.声明性SQL语句。 1. 触发器,2. 其他存储过程以及3. Java,Python,PHP等应用程序可以调用存储过程。
    
    2.mysql主要高级的功能:存储过程,存储函数,触发器和事件  
    
    3.优点是: 减轻web服务器的压力, 将些业务转移到sql 服务器去
    4.--------------------------------------
    5.创建一个名字叫做:GetAllProducts()的存储过程
    DELIMITER //
     CREATE PROCEDURE GetAllProducts()
       BEGIN
       SELECT *  FROM products;
       END //DELIMITER ;
    6.调用存储过程
    CALL STORED_PROCEDURE_NAME();
    7.--------------------------------------
    声明变量:DECLARE variable_name datatype(size) DEFAULT default_value;
    set分配变量:DECLARE total_count INT DEFAULT 0;SET total_count = 10;
    Set Into 分配变量:DECLARE total_products INT DEFAULT 0
    SELECT COUNT(*) INTO total_productsFROM products
    8.作用域问题: 一般作用域是 begin 到end , 然后加上@ 是属于会话变量,在其他存储过程也可以使用
    定义参数:MODE param_name param_type(param_size)
    根据存储过程中参数的目的,MODE可以是IN,OUT或INOUT。
    In的实例:USE `yiibaidb`;DROP procedure IF EXISTS `GetOfficeByCountry`;
    DELIMITER $$USE `yiibaidb`$$CREATE PROCEDURE GetOfficeByCountry(IN countryName VARCHAR(255))
     BEGIN
     SELECT * 
     FROM offices
     WHERE country = countryName;
     END$$
    DELIMITER ;
    
    CALL GetOfficeByCountry('USA');
    CALL GetOfficeByCountry('USA');
    
    
    Out的实例:USE `yiibaidb`;DROP procedure IF EXISTS `CountOrderByStatus`;
    DELIMITER $$CREATE PROCEDURE CountOrderByStatus(
     IN orderStatus VARCHAR(25),
     OUT total INT)BEGIN
     SELECT count(orderNumber)
     INTO total
     FROM orders
     WHERE status = orderStatus;END$$DELIMITER ;
    
    CALL CountOrderByStatus('Shipped',@total);
    SELECT @total;  #赋值给全局的变量
    
    Inout的实例DELIMITER $$CREATE PROCEDURE set_counter(INOUT count INT(4),IN inc INT(4))BEGIN
     SET count = count + inc;END$$DELIMITER ;
    
    #关于全局的变量值的处理
    SET @counter = 1;
    CALL set_counter(@counter,1); -- 2
    CALL set_counter(@counter,1); -- 3
    CALL set_counter(@counter,5); -- 8
    SELECT @counter; -- 8
    
    9.关于 mybaties中调用存储过程的代码: 
    <!-- 调用存储过程递归删除部门以及部门下的所有子部门 -->
        <delete id="deleteProcedureById" statementType="CALLABLE">
          { call delete_department(#{id, mode=IN}) }
       </delete>
    根据手册 可以查到, 别照抄老师代码:http://www.mybatis.org/mybatis-3/sqlmap-xml.html
    
    10.返回多个值的存储过程示例
    DELIMITER $$
    CREATE PROCEDURE get_order_by_cust(
     IN cust_no INT,
     OUT shipped INT,
     OUT canceled INT,
     OUT resolved INT,
     OUT disputed INT)BEGIN
     -- shipped
     SELECT
                count(*) INTO shipped
            FROM
                orders
            WHERE
                customerNumber = cust_no
                    AND status = 'Shipped';
    
     -- canceled
     SELECT
                count(*) INTO canceled
            FROM
                orders
            WHERE
                customerNumber = cust_no
                    AND status = 'Canceled';
    
     -- resolved
     SELECT
                count(*) INTO resolved
            FROM
                orders
            WHERE
                customerNumber = cust_no
                    AND status = 'Resolved';
    
     -- disputed
     SELECT
                count(*) INTO disputed
            FROM
                orders
            WHERE
                customerNumber = cust_no
                    AND status = 'Disputed';
    END
    11.条件语句
    IF expression THEN
       statements;ELSE
       else-statements;END IF;
    12.选择语句
    CASE  case_expression
       WHEN when_expression_1 THEN commands
       WHEN when_expression_2 THEN commands
       ...
       ELSE commandsEND CASE;
    13.循环
    WHILE语句的语法如下:
    WHILE expression DO
       statementsEND WHILE
    WHILE语句的语法如下:
    WHILE expression DO
       Statements
    END WHILE
    
     loop_label:  LOOP
     IF  x > 10 THEN 
     LEAVE  loop_label;
     END  IF;
    14.游标
    存储函数和触发器中使用MySQL游标。
    处理存储过程中的结果集,请使用游标。游标允许您迭代查询返回的一组行,并相应地处理每行。
    MySQL游标为只读,不可滚动和敏感。
    敏感:有两种游标:敏感游标和不敏感游标。敏感游标指向实际数据,不敏感游标使用数据的临时副本。
    不可滚动:只能按照SELECT语句确定的顺序获取行,不可 跳转取,不可逆向取
    
    声明游标:
    DECLARE cursor_name CURSOR FOR SELECT_statement;
    游标声明必须在变量声明之后
    OPEN cursor_name;
    
    FETCH cursor_name INTO variables list;
    CLOSE cursor_name;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
    15.显示存储过程的语句
    根据数据库:SHOW PROCEDURE STATUS WHERE db = 'yiibaidb';
    根据存储过程的名字模糊查询:SHOW PROCEDURE STATUS WHERE name LIKE '%product%'
    根据名字直接查询:SHOW CREATE PROCEDURE stored_procedure_name
    
    16.声明处理程序(比如错误)
    DECLARE action HANDLER FOR condition_value statement;
    SQL
    如果条件的值与condition_value匹配,则MySQL将执行statement,并根据该操作继续或退出当前的代码块。
    操作(action)接受以下值之一:
    CONTINUE:继续执行封闭代码块(BEGIN ... END)。
    EXIT:处理程序声明封闭代码块的执行终止。
    condition_value指定一个特定条件或一类激活处理程序的条件。condition_value接受以下值之一:
    一个MySQL错误代码。
    标准SQLSTATE值或者它可以是SQLWARNING,NOTFOUND或SQLEXCEPTION条件,这是SQLSTATE值类的简写。NOTFOUND条件用于游标或SELECT INTO variable_list语句。
    与MySQL错误代码或SQLSTATE值相关联的命名条件。
    例如:DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET has_error = 1;
    DECLARE EXIT HANDLER FOR SQLEXCEPTIONBEGINROLLBACK;SELECT 'An error has occurred, operation rollbacked and the stored procedure was terminated';END;
    17.Mysql 处理的优先级, 是错误代码最为具体, 所以错误代码优先级最高
    18.声明命名错误的条件:
    DECLARE condition_name CONDITION FOR condition_value;
    
    DECLARE table_not_found CONDITION for 1051;DECLARE EXIT HANDLER FOR  table_not_found SELECT 'Please create table abc first';SELECT * FROM abc;
    19.添加返回的错误信息,根据错误码
    SIGNAL SQLSTATE '45000'
     SET MESSAGE_TEXT = 'Order No not found in orders table';
    
    
     DECLARE division_by_zero CONDITION FOR SQLSTATE '22012';
    
     DECLARE CONTINUE HANDLER FOR division_by_zero 
     RESIGNAL SET MESSAGE_TEXT = 'Division by zero / Denominator cannot be zero';
    20.存储函数
    CREATE FUNCTION function_name(param1,param2,…)
        RETURNS datatype
       [NOT] DETERMINISTIC
     statements
    21.
    12

    2018-01-15

    ------------------------------------------不能下载所以只能贴出来:

    题目部分:

    1. 利用存储过程求出,product的总数来

    2. 将product中的商品数量放置到 变量 total_product中去

    3. 根据Country查到office, 要求是输入的变量必须是countryName int

    4. 过订单状态返回订单数量。参数分别为:in orderStatus varchar(255) ,out total int

    5. 穿入一个参数inout类型 a, 还有一个int类型的参数 b, 存储过程a = a + b, 这样a既是输入也是输出参数

    6. 输入4customerNumber ,和status ,来获取, 输入shipped canceled resolved disputed

    7. 根据customerNumber获取creditlimit,然后据此进行判断是在哪个区间 10000 50000

    8. 根据customerNumber 获取customerCountry, 然后据此进行判断举办活动的时间是几天

    9. 将1到5 拼成字符串, while do end while , repeat until end repeat,

    10. email_list,字符串放进去,利用游标和concat进行拼接得到varcahr类型

    11. 创建一张表, 然后自己做实验, 如果出现重复出现的结果的时候可以报你插入的地方重复插入

    #1. get allProduct
    DELIMITER $$
    CREATE PROCEDURE GetAllProduck()
    BEGIN
    SELECT * FROM products;
    END $$
    DELIMITER ;
    
    CALL GetAllProduck()
    
    #2. 将product中的商品数量放置到 变量 total_product中去
    DELIMITER $$
    CREATE PROCEDURE countProduct4()
    BEGIN
    DECLARE count_products INT DEFAULT 0;
    #set count_products = xxx;
    SELECT COUNT(*) INTO count_products FROM products;
    END $$
    DELIMITER ;
    
    #3. 根据countryName 查到office
    DELIMITER $$
    CREATE    PROCEDURE getOfficeByCountry(IN countryName VARCHAR(255))
    BEGIN    
    SELECT * FROM offices 
    WHERE country = countryName;
    END $$
    
    CALL getOfficeByCountry2('China')
    
    #4. 过订单状态返回订单数量
    USE yiibaidb;
    DROP PROCEDURE IF EXISTS CountryOrderByStatus;
    
    DELIMITER $$
    CREATE    PROCEDURE CountryOrderByStatus(IN orderStatus VARCHAR(25), OUT total INT )
    BEGIN
    SELECT COUNT(orderNumber)
     INTO total 
     FROM orders
    WHERE STATUS = orderStatus;
    END$$
    DELIMITER ;
    
    CALL     CountryOrderByStatus('Shipped', @total);
    #  '@'符号标志的会话变量会等会话结束后才会over, 可以想成一个connection结束。 其他时候可以直接select @变量获得
    SELECT    @total;
    
    #5. a = a + b
    #use yiibaidb;
    DROP PROCEDURE  IF EXISTS addTwoNum ;
    DELIMITER $$
    CREATE PROCEDURE addTwoNum(INOUT a INT, IN b INT)
    BEGIN    
    SET a = a + b;
    END $$
    DELIMITER ; #delimiter 这里必须得空格不然会报错
    
    SET @a = 1;
    CALL addTwoNum(@a ,     4);
    SELECT @a;
    
    #6. 根据orderNumber, 返回status4种类型的数量
    DROP PROCEDURE IF EXISTS get_order_by_cust;
    
    DELIMITER $$
    
    CREATE PROCEDURE get_order_by_cust(
     IN cust_no INT,
     OUT shipped INT,
     OUT canceled INT,
     OUT resolved INT,
     OUT disputed INT)
    BEGIN
     -- shipped
     SELECT
                COUNT(*) INTO shipped
            FROM
                orders
            WHERE
                customerNumber = cust_no
                    AND STATUS = 'Shipped';
                    
     -- canceled
     SELECT
                COUNT(*) INTO canceled
            FROM
                orders
            WHERE
                customerNumber = cust_no
                    AND STATUS = 'Cancelled';
    
     -- resolved
     SELECT
                COUNT(*) INTO resolved
            FROM
                orders
            WHERE
                customerNumber = cust_no
                    AND STATUS = 'Resolved';
    
     -- disputed
     SELECT
                COUNT(*) INTO disputed
            FROM
                orders
            WHERE
                customerNumber = cust_no
                    AND STATUS = 'Disputed';                
    END $$
    DELIMITER ;
    
    CALL get_order_by_cust(496, @shipped , @canceled , @resolved , @disputed);
    SELECT @shipped , @canceled , @resolved , @disputed;
    
    #7. 根据customerNumber获取creditlimit,然后据此进行判断是在哪个区间 10000 50000
    
    DELIMITER $$
    CREATE PROCEDURE GetCustomerLevel(IN p_customerNumber INT(11), OUT p_customerLevel VARCHAR(10) )
    BEGIN
    
    DECLARE creditlim  DOUBLE;
    
    SELECT creditLimit INTO creditlim 
    FROM customers
    WHERE customerNumber = p_customerNumber;
    
    IF creditlim>50000 THEN    
    SET p_customerLevel = 'PLATINUM';
    
    ELSEIF (creditlim>10000 AND creditlim<=50000) THEN
    
    SET p_customerLevel = 'GOLD';
    
    ELSEIF creditlim<=10000 THEN
    
    SET p_customerLevel = 'SILVER';
    
    END IF;
    
    END $$
    DELIMITER ;
    
    CALL GetCustomerLevel(103, @customerLevel);
    SELECT @customerLevel;
    
    
    DELIMITER $$
    CREATE PROCEDURE GetCustomerShipping(IN p_customerNumber INT(4),  OUT p_shiping  VARCHAR(50))
    BEGIN
    DECLARE customerCountry VARCHAR(50);
    
    SELECT country INTO customerCountry
    FROM customers 
    WHERE customerNumber = p_customerNumber;
    
    CASE customerCountry
    
    WHEN 'USA' THEN
      SET p_shiping  = '2-day Shipping';  
    WHEN 'Canada' THEN
      SET p_shiping  = '3-day Shipping';
    ELSE
      SET p_shiping  = '4-day Shipping';
    END CASE;
    END $$
    DELIMITER ;
    
    #调用加别名,自己组成表格形式更加好看见       
    CALL GetCustomerShipping(112,@shipping);
    SELECT @shipping AS Shipping
    
    SET @customerNo = 112;
    
    SELECT country INTO @country
    FROM customers
    WHERE customernumber = @customerNo;
    
    CALL GetCustomerShipping(@customerNo,@shipping);
    
    SELECT @customerNo AS Customer,
           @country    AS Country,
           @shipping   AS Shipping;
           
    
    #上一题区间题目用case进行实现
    DELIMITER $$
    CREATE PROCEDURE GetCustomerLevel(
     in  p_customerNumber int(11), 
     out p_customerLevel  varchar(10))BEGIN
        DECLARE creditlim double;
    
        SELECT creditlimit INTO creditlim
     FROM customers
     WHERE customerNumber = p_customerNumber;
    
        CASE  
     WHEN creditlim > 50000 THEN 
        SET p_customerLevel = 'PLATINUM';
     WHEN (creditlim <= 50000 AND creditlim >= 10000) THEN
        SET p_customerLevel = 'GOLD';
     WHEN creditlim < 10000 THEN
        SET p_customerLevel = 'SILVER';
     END CASE;
    END$$
    
    #9.将1到5 拼成字符串
    
    
    #循环遍历while ... do 形式
    DELIMITER $$
    DROP PROCEDURE IF EXISTS test_mysql_while_loop1$$
    CREATE PROCEDURE test_mysql_while_loop1()
    BEGIN    
    DECLARE X INT(4);
    DECLARE str VARCHAR(50);
    
    SET X = 1; 
    SET str = '';
    
    WHILE X <= 5 DO 
    SET str = CONCAT(str, X, ',');
    SET X = X +1;
    END WHILE ;
    SELECT str AS num, X AS number;
    
     END$$
    DELIMITER ;
    
    CALL test_mysql_while_loop1;
    
    
    
    #循环遍历repeat ... until ... end repeat 形式
    DELIMITER $$
    DROP PROCEDURE IF EXISTS test_mysql_while_loop2$$
    CREATE PROCEDURE test_mysql_while_loop2()
    BEGIN    
    DECLARE X INT(4);
    DECLARE str VARCHAR(50);
    
    SET X = 1; 
    SET str = '';
    
    REPEAT 
    SET str = CONCAT(str, X, ',');
    SET X = X +1 ;
    UNTIL X >5
    END REPEAT;
    SELECT str AS num, X AS number;
    
     END$$
    DELIMITER ;
    
    CALL test_mysql_while_loop2;
    
    
    
    
    #循环遍历loop_label .... end loop, 中间会有leave loop_label进行退出, Iterate进行迭代
    DELIMITER $$
    DROP PROCEDURE IF EXISTS test_mysql_while_loop2$$
    CREATE PROCEDURE test_mysql_while_loop2()
    BEGIN    
    DECLARE X INT(4);
    DECLARE str VARCHAR(50);
    
    SET X = 1; 
    SET str = '';
    
     loop_label:  LOOP
     IF  X > 10 THEN 
     LEAVE  loop_label;
     END  IF;
    
     SET  X = X + 1;
     IF (X MOD 3) THEN
         ITERATE  loop_label;
     ELSE
        SET  str = CONCAT(str,X,',');
     END IF;
        END LOOP;    
    SELECT str AS num, X AS number;
    
     END$$
    DELIMITER ;
    
    CALL test_mysql_while_loop2;
    
    
    #游标的用法,email_list,字符串放进去,利用游标和concat进行拼接得到varcahr类型
    DELIMITER $$
    DROP PROCEDURE IF EXISTS build_email_list $$
    CREATE PROCEDURE build_email_list(INOUT p_email VARCHAR(500))
    BEGIN    
    DECLARE v_finished INTEGER DEFAULT 0;
    DECLARE v_email VARCHAR(100) DEFAULT '';
    
    -- declare cusor for the empolyee email
    DECLARE email_cusor CURSOR FOR 
    SELECT email FROM employees;
    
    -- decalre NOT FOUND hander
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1;
    
    OPEN email_cusor;
    
    get_email:LOOP
    
    FETCH email_cusor INTO v_email;
    
    -- 进行跳出判断
    IF v_finished = 1 THEN 
    LEAVE get_email;
    END IF;
    
    SET p_email = CONCAT(v_email, ';', p_email);
    
    END LOOP get_email;
    
    CLOSE email_cusor;
    
    END $$
    DELIMITER ;
    
    SET @email_list = "";
    CALL build_email_list(@email_list);
    SELECT @email_list;
    
    #11. 创建一张表, 然后自己做实验, 如果出现重复出现的结果的时候可以报你插入的地方重复插入, EXITcontinue
    DELIMITER $$
    DROP PROCEDURE IF EXISTS insertException $$
    CREATE PROCEDURE insertException(IN article_id INT, IN tag_id INT )
    BEGIN 
    -- 进行声明出现重复代码1062的时候输出
     DECLARE CONTINUE HANDLER FOR 1062
     SELECT CONCAT('duplicate found the (',article_id,',',tag_id,')') AS msg;
     
     INSERT INTO article_tags(article_id,tag_id)
     VALUES(article_id,tag_id);
    
     -- return tag count for the article
     SELECT COUNT(*) FROM article_tags AS a WHERE a.article_id =article_id AND  a.tag_id =tag_id;
    
    END $$
    DELIMITER ;
    
    CALL insertException(1,1);
    CALL insertException(1,2);
    CALL insertException(1,3);
    
    
    
    #利用函数进行判断: create function xxx(param )returns type()
    #Deterministic ...   return (variable)
    - - 
    DELIMITER $$
    DROP FUNCTION IF EXISTS CustomerLevel6 $$
    CREATE FUNCTION CustomerLevel6(p_creditLimit DOUBLE )RETURNS VARCHAR(10)
        DETERMINISTIC
    BEGIN 
        DECLARE 1v1 VARCHAR(10);
        
        IF p_creditLimit > 50000 THEN 
      SET 1v1 = 'jinzi';
        ELSEIF (p_creditLimit > 10000 AND p_creditLimit <= 50000  ) THEN 
      SET 1v1 = 'yinzi';
         ELSEIF p_creditLimit <= 10000 THEN 
      SET 1v1 = 'baijin';
      END IF ;
      RETURN (1v1);
      END $$
      DELIMITER ;
      
    
    SELECT 
        customerName, CustomerLevel6(creditLimit)
    FROM
        customers
    ORDER BY customerName;  
    题目的sql

    ------------关于实例的sql数据库文档 -- 留言发邮箱

  • 相关阅读:
    React生命周期及事件详解
    系统重装后常见的环境变量配置
    Java 字符串格式化
    React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发
    java-json与js-json转化
    RN项目中缩进处理
    React Native 常用学习链接地址
    React-Native 常用组件学习资料链接
    Swift-继承、构造器、类型转换(嵌套)、类扩展、泛型、协议
    CallKit详解(来电提醒+骚扰拦截)
  • 原文地址:https://www.cnblogs.com/jwlxtf/p/8288288.html
Copyright © 2020-2023  润新知