• MySQL存储过程(转)


    一、MySQL 创建存储过程 
    “pr_add” 是个简单的 MySQL 存储过程,这个存储过程有两个 int 类型的输入参数 “a”、“b”,返回这两个参数的和。

    drop procedure if exists pr_add;
    -- 计算两个数之和
    create procedure pr_add
    (
       a int,
       b int
    )
    begin
       declare c int;
       if a is null then
          set a = 0;
       end if;
       if b is null then
          set b = 0;
       end if;
       set c = a + b;
       select c as sum;
       /*
       return c;- 不能在 MySQL 存储过程中使用。return 只能出现在函数中。
      /
    end;
     
    二、调用Mysql存储过程
    eg: call pr_add(10,20);
     
    执行 MySQL 存储过程,存储过程参数为 MySQL 用户变量。
    set @a = 10;
    set @b = 20;
    call pr_add(@a, @b);
     
    三、MySQL 存储过程特点 
    创建 MySQL 存储过程的简单语法为:
    create procedure 存储过程名字()
    (
       [in|out|inout] 参数 datatype
    )
    begin
       MySQL 语句;
    end;
    MySQL 存储过程参数如果不显式指定“in”、“out”、“inout”,则默认为“in”。习惯上,对于是“in” 的参数,我们都不会显式指定。
     
    如下,给出解释
    1. MySQL 存储过程名字后面的“()”是必须的,即使没有一个参数,也需要“()”
     
    2. MySQL 存储过程参数,不能在参数名称前加“@”,如:“@a int”。下面的创建存储过程语法在 MySQL 中是错误的(在 SQL Server 中是正确的)。 MySQL 存储过程中的变量,不需要在变量名字前加“@”,虽然 MySQL 客户端用户变量要加个“@”。
    create procedure pr_add
    (
       @a int,- 错误
       b int   - 正确
    )
     
    3. MySQL 存储过程的参数不能指定默认值。
     
    4. MySQL 存储过程不需要在 procedure body 前面加 “as”。而 SQL Server 存储过程必须加 “as” 关键字。
    create procedure pr_add
    (
       a int,
       b int
    )
    as             - 错误,MySQL 不需要 “as”
    begin
       mysql statement ...;
    end;
     
    5. 如果 MySQL 存储过程中包含单条或者多条 MySQL 语句,都需要 begin end 关键字。
    create procedure pr_add
    (
       a int,
       b int
    )
    begin
       mysql statement 1 ...;
       mysql statement 2 ...;
    end;
     
    6.MySQL 存储过程中的每条语句的末尾,都要加上分号 “;”
       ...
       declare c int;
       if a is null then
          set a = 0;
       end if;
       ...
     
    7. MySQL 存储过程中的注释。
       /*
         这是个
         多行 MySQL 注释。
      /
    declare c int;    - 这是单行 MySQL 注释 (注意- 后至少要有一个空格)
       if a is null then 这也是个单行 MySQL 注释
          set a = 0;
       end if;
       ...
    end;
     
    8. 不能在 MySQL 存储过程中使用 “return” 关键字。
       set c = a + b;
       select c as sum;
       /*
       return c;- 不能在 MySQL 存储过程中使用。return 只能出现在函数中。
      /
    end;

    9. 调用 MySQL 存储过程时候,需要在过程名字后面加“()”,即使没有一个参数,也需要“()”
    call pr_no_param();

    10. 因为 MySQL 存储过程参数没有默认值,所以在调用 MySQL 存储过程时候,不能省略参数。可以用 null 来替代。
    call pr_add(10, null);
    1、当然以上这些,前提是 mysql 5
     
    2、下面写一个mysql存储过程之 Hello  World
    1. DELIMITER $$   
    2.   
    3. DROP PROCEDURE IF EXISTS HelloWorld$$   
    4. CREATE PROCEDURE HelloWorld()   
    5. BEGIN   
    6.     SELECT "Hello World!";   
    7. END$$   
    8.   
    9. DELIMITER ; 

    3、变量

              使用DECLARE来声明,DEFAULT赋默认值,SET赋值 

    1. DECLARE counter INT DEFAULT 0;  - 默认为0
    2. SET counter = counter+1;              - 自增+1

    4、参数

    IN为默认类型,值必须在调用时指定,值不能返回(值传递) 
    OUT值可以返回(指针传递) 
    INOUT值必须在调用时指定,值可以返回 

    eg:

    1. CREATE PROCEDURE test(a INT, OUT b FLOAT, INOUT c INT)  

    5、条件判断

    eg:

    1. DELIMITER $$   
    2.   
    3. DROP PROCEDURE IF EXISTS discounted_price$$   
    4. CREATE PROCEDURE discunted_price(normal_price NUMERIC(8, 2), OUT discount_price NUMERIC(8, 2))   
    5. BEGIN   
    6.     IF (normal_price > 500) THEN   
    7.         SET discount_price = normal_price * .8;   
    8.     ELSEIF (normal_price > 100) THEN   
    9.         SET discount_price = normal_price * .9;   
    10.     ELSE   
    11.         SET discount_price = normal_price;   
    12.     END IF;   
    13. END$$   
    14.   
    15. DELIMITER ;  

    6、循环

    LOOPEND LOOP 

    eg:

    1. DELIMITER $$   
    2.   
    3. DROP PROCEDURE IF EXISTS simple_loop$$   
    4.   
    5. CREATE PROCEDURE simple_loop(OUT counter INT)   
    6. BEGIN   
    7.     SET counter = 0;   
    8.     my_simple_loop: LOOP   
    9.         SET counter = counter+1;   
    10.         IF counter = 10 THEN   
    11.             LEAVE my_simple_loop;   
    12.         END IF;   
    13.     END LOOP my_simple_loop;   
    14. END$$   
    15.   
    16. DELIMITER ;  

    WHILE DOEND WHILE 

     
    1. DELIMITER $$   
    2.   
    3. DROP PROCEDURE IF EXISTS simple_while$$   
    4.   
    5. CREATE PROCEDURE simple_while(OUT counter INT)   
    6. BEGIN   
    7.     SET counter = 0;   
    8.     WHILE counter != 10 DO   
    9.         SET counter = counter+1;   
    10.     END WHILE;   
    11. END$$   
    12.   
    13. DELIMITER ;  


    REPEATUNTILL 

     
    1. DELIMITER $$   
    2.   
    3. DROP PROCEDURE IF EXISTS simple_repeat$$   
    4.   
    5. CREATE PROCEDURE simple_repeat(OUT counter INT)   
    6. BEGIN   
    7.     SET counter = 0;   
    8.     REPEAT   
    9.         SET counter = counter+1;   
    10.     UNTIL counter = 10 END REPEAT;   
    11. END$$   
    12.   
    13. DELIMITER ;  



    7,异常处理 
    如果用cursor获取SELECT语句返回的所有结果集时应该定义NOT FOUND error handler来防止存储程序提前终结 
    如果SQL语句可能返回constraint violation等错误时应该创建一个handler来防止程序终结 

    8,数据库交互 
    INTO用于存储单行记录的查询结果 

     
    1. DECLARE total_sales NUMERIC(8, 2);   
    2. SELECT SUM(sale_value) INTO total_sales FROM sales WHERE customer_id=in_customer_id;  



    CURSOR用于处理多行记录的查询结果 

     
    1. DELIMITER $$   
    2.   
    3. DROP PROCEDURE IF EXITS cursor_example$$   
    4. CREATE PROCEDURE cursor_example()   
    5.     READS SQL DATA   
    6. BEGIN   
    7.     DECLARE l_employee_id INT;   
    8.     DECLARE l_salary NUMERIC(8,2);   
    9.     DECLARE l_department_id INT;   
    10.     DECLARE done INT DEFAULT 0;   
    11.     DECLARE cur1 CURSOR FOR SELECT employee_id, salary, department_id FROM employees;   
    12.     DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;   
    13.   
    14.     OPEN cur1;   
    15.     emp_loop: LOOP   
    16.         FETCH cur1 INTO l_employee_id, l_salary, l_department_id;   
    17.         IF done=1 THEN   
    18.             LEAVE emp_loop;   
    19.         END IF;   
    20.     END LOOP emp_loop;   
    21.     CLOSE cur1;   
    22. END$$   
    23. DELIMITER ;  



    unbounded SELECT语句用于存储过程返回结果集 

     
    1. DELIMITER $$   
    2. DROP PROCEDURE IF EXISTS sp_emps_in_dept$$   
    3. CREATE PROCEDURE sp_emps_in_dept(in_employee_id INT)   
    4. BEGIN   
    5.     SELECT employee_id, surname, firstname, address1, address2, zipcode, date_of_birth FROM employees WHERE department_id=in_employee_id;   
    6. END$$   
    7.   
    8. DELIMITER ;  



    UPDATE、INSERT、DELETE、CREATE TABLE等非查询语句也可以嵌入存储过程里 

     
    1. DELIMITER $$   
    2.   
    3. DROP PROCEDURE IF EXITS sp_update_salary$$   
    4. CREATE PROCEDURE sp_update_salary(in_employee_id INT, in_new_salary NUMERIC(8,2))   
    5. BEGIN   
    6.     IF in_new_salary < 5000 OR in_new_salary > 500000 THEN   
    7.         SELECT "Illegal salary: salary must be between $5000 and $500, 000";   
    8.     ELSE   
    9.         UPDATE employees SET salary=in_new_salary WHERE employee_id=in_employee_id;   
    10.     END IF:   
    11. END$$   
    12.   
    13. DELIMITER ;  



    9,使用CALL调用存储程序 

     
    1. DELIMITER $$   
    2.   
    3. DROP PROCEDURE IF EXISTS call_example$$   
    4. CREATE PROCEDURE call_example(employee_id INT, employee_type VARCHAR(20))   
    5.     NO SQL   
    6. BEGIN   
    7.     DECLARE l_bonus_amount NUMERIC(8,2);   
    8.   
    9.     IF employee_type='MANAGER' THEN   
    10.         CALL calc_manager_bonus(employee_id, l_bonus_amount);   
    11.     ELSE   
    12.         CALL calc_minion_bonus(employee_id, l_bonus_amount);   
    13.     END IF;   
    14.     CALL grant_bonus(employee_id, l_bonus_amount);   
    15. END$$   
    16. DELIMITER ;  



    10,一个复杂的例子 

     
    1. CREATE PROCEDURE putting_it_all_together(in_department_id INT)   
    2.     MODIFIES SQL DATA   
    3. BEGIN   
    4.     DECLARE l_employee_id INT;   
    5.     DECLARE l_salary NUMERIC(8,2);   
    6.     DECLARE l_department_id INT;   
    7.     DECLARE l_new_salary NUMERIC(8,2);   
    8.     DECLARE done INT DEFAULT 0;   
    9.   
    10.     DECLARE cur1 CURSOR FOR   
    11.         SELECT employee_id, salary, department_id   
    12.         FROM employees   
    13.         WHERE department_id=in_department_id;   
    14.   
    15.     DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;   
    16.   
    17.     CREATE TEMPORARY TABLE IF NOT EXISTS emp_raises   
    18.         (employee_id INT, department_id INT, new_salary NUMERIC(8,2));   
    19.   
    20.     OPEN cur1;   
    21.     emp_loop: LOOP   
    22.         FETCH cur1 INTO l_employee_id, l_salary, l_department_id;   
    23.         IF done=1 THEN    /* No more rows */  
    24.             LEAVE emp_loop;   
    25.         END IF;   
    26.         CALL new_salary(1_employee_id, l_new_salary); /* Get new salary */  
    27.         IF (l_new_salary <> l_salary) THEN  /* Salary changed */  
    28.             UPDATE employees   
    29.                 SET salary=l_new_salary   
    30.             WHERE employee_id=l_employee_id;   
    31.             /* Keep track of changed salaries */  
    32.             INSERT INTO emp_raises(employee_id, department_id, new_salary)   
    33.                 VALUES (l_employee_id, l_department_id, l_new_salary);   
    34.         END IF:   
    35.     END LOOP emp_loop;   
    36.     CLOSE cur1;   
    37.     /* Print out the changed salaries */  
    38.     SELECT employee_id, department_id, new_salary from emp_raises   
    39.         ORDER BY employee_id;   
    40. END;  



    11,存储方法 
    存储方法与存储过程的区别 
    1,存储方法的参数列表只允许IN类型的参数,而且没必要也不允许指定IN关键字 
    2,存储方法返回一个单一的值,值的类型在存储方法的头部定义 
    3,存储方法可以在SQL语句内部调用 
    4,存储方法不能返回结果集 
    语法: 

     
    1. CREATE   
    2.     [DEFINER = { user | CURRENT_USER }]   
    3.     PROCEDURE sp_name ([proc_parameter[,...]])   
    4.     [characteristic ...] routine_body   
    5.   
    6. CREATE   
    7.     [DEFINER = { user | CURRENT_USER }]   
    8.     FUNCTION sp_name ([func_parameter[,...]])   
    9.     RETURNS type   
    10.     [characteristic ...] routine_body   
    11.        
    12. proc_parameter:   
    13.     [ IN | OUT | INOUT ] param_name type   
    14.        
    15. func_parameter:   
    16.     param_name type   
    17.   
    18. type:   
    19.     Any valid MySQL data type   
    20.   
    21. characteristic:   
    22.     LANGUAGE SQL   
    23.   | [NOT] DETERMINISTIC   
    24.   | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }   
    25.   | SQL SECURITY { DEFINER | INVOKER }   
    26.   | COMMENT 'string'  
    27.   
    28. routine_body:   
    29.     Valid SQL procedure statement  


    各参数说明见CREATE PROCEDURE and CREATE FUNCTION Syntax 
    例子: 

     
    1. DELIMITER $$   
    2.   
    3. DROP FUNCTION IF EXISTS f_discount_price$$   
    4. CREATE FUNCTION f_discount_price   
    5.     (normal_price NUMERIC(8,2))   
    6.     RETURNS NUMERIC(8,2)   
    7.     DETERMINISTIC   
    8. BEGIN   
    9.     DECLARE discount_price NUMERIC(8,2);   
    10.   
    11.     IF (normal_price > 500) THEN   
    12.         SET discount_price = normal_price * .8;   
    13.     ELSEIF (normal_price >100) THEN   
    14.         SET discount_price = normal_price * .9;   
    15.     ELSE   
    16.         SET discount_price = normal_price;   
    17.     END IF;   
    18.   
    19.     RETURN(discount_price);   
    20. END$$   
    21.   
    22. DELIMITER ;  



    12,触发器 
    触发器在INSERT、UPDATE或DELETE等DML语句修改数据库表时触发 
    触发器的典型应用场景是重要的业务逻辑、提高性能、监控表的修改等 
    触发器可以在DML语句执行前或后触发 

     
      1. DELIMITER $$   
      2.   
      3. DROP TRIGGER sales_trigger$$   
      4. CREATE TRIGGER sales_trigger   
      5.     BEFORE INSERT ON sales   
      6.     FOR EACH ROW   
      7. BEGIN   
      8.     IF NEW.sale_value > 500 THEN   
      9.         SET NEW.free_shipping = 'Y';   
      10.     ELSE   
      11.         SET NEW.free_shipping = 'N';   
      12.     END IF;   
      13.   
      14.     IF NEW.sale_value > 1000 THEN   
      15.         SET NEW.discount = NEW.sale_value * .15;   
      16.     ELSE   
      17.         SET NEW.discount = 0;   
      18.     END IF;   
      19. END$$   
      20.   
      21. DELIMITER ; 
  • 相关阅读:
    ASP.NET Web API 控制器执行过程(一)
    ASP.NET Web API 控制器创建过程(二)
    ASP.NET Web API 控制器创建过程(一)
    ASP.NET Web API WebHost宿主环境中管道、路由
    ASP.NET Web API Selfhost宿主环境中管道、路由
    ASP.NET Web API 管道模型
    ASP.NET Web API 路由对象介绍
    ASP.NET Web API 开篇示例介绍
    ASP.NET MVC 视图(五)
    ASP.NET MVC 视图(四)
  • 原文地址:https://www.cnblogs.com/kuangwong/p/6252185.html
Copyright © 2020-2023  润新知