`
javasee
  • 浏览: 924327 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Stupid PHPmyadmin,让我的存储过程一点都不能正确建立,还以为错了

 
阅读更多

在PHPmyadmin中,我们不能用 "delimiter //" 来指定分隔符,而应当在SQl窗口中手工把 ";" 改为 "//" ,要不我们总是会得到建立存储过程错误的信息——如果你的存储过程用";"来分隔的话。

以下顺便转载一篇不错的Mysql存储过程实例教程:

转载自:http://blog.aladada.com/Joince/2009/02/12/17999

MySQL 存储过程是从 MySQL 5.0 开始增加的新功能。存储过程的优点有一箩筐。不过最主要的还是执行效率和SQL 代码封装。特别是 SQL 代码封装功能,如果没有存储过程,在外部程序访问数据库时(例如 PHP),要组织很多 SQL 语句。特别是业务逻辑复杂的时候,一大堆的 SQL 和条件夹杂在 PHP 代码中,让人不寒而栗。现在有了 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 存储过程
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;

...
end;
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);

还有这个:http://blog.aladada.com/Joince/2009/02/12/18000

1,前提
需要MySQL 5

2,Hello World
MySQL存储过程之Hello World

Java代码 复制代码
  1. DELIMITER$$
  2. DROPPROCEDUREIFEXISTSHelloWorld$$
  3. CREATEPROCEDUREHelloWorld()
  4. BEGIN
  5. SELECT "HelloWorld!" ;
  6. END$$
  7. DELIMITER;



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

Java代码 复制代码
  1. DECLAREcounterINTDEFAULT 0 ;
  2. SETcounter=counter+ 1 ;



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

Java代码 复制代码
  1. CREATEPROCEDUREtest(aINT,OUTbFLOAT,INOUTcINT)



5,条件判断
IF THENELSEIFELSEEND IF

Java代码 复制代码
  1. DELIMITER$$
  2. DROPPROCEDUREIFEXISTSdiscounted_price$$
  3. CREATEPROCEDUREdiscunted_price(normal_priceNUMERIC( 8 , 2 ),OUTdiscount_priceNUMERIC( 8 , 2 ))
  4. BEGIN
  5. IF(normal_price> 500 )THEN
  6. SETdiscount_price=normal_price*. 8 ;
  7. ELSEIF(normal_price> 100 )THEN
  8. SETdiscount_price=normal_price*. 9 ;
  9. ELSE
  10. SETdiscount_price=normal_price;
  11. ENDIF;
  12. END$$
  13. DELIMITER;



6,循环
LOOPEND LOOP

Java代码 复制代码
  1. DELIMITER$$
  2. DROPPROCEDUREIFEXISTSsimple_loop$$
  3. CREATEPROCEDUREsimple_loop(OUTcounterINT)
  4. BEGIN
  5. SETcounter= 0 ;
  6. my_simple_loop:LOOP
  7. SETcounter=counter+ 1 ;
  8. IFcounter= 10 THEN
  9. LEAVEmy_simple_loop;
  10. ENDIF;
  11. ENDLOOPmy_simple_loop;
  12. END$$
  13. DELIMITER;


WHILE DOEND WHILE

Java代码 复制代码
  1. DELIMITER$$
  2. DROPPROCEDUREIFEXISTSsimple_while$$
  3. CREATEPROCEDUREsimple_while(OUTcounterINT)
  4. BEGIN
  5. SETcounter= 0 ;
  6. WHILEcounter!= 10 DO
  7. SETcounter=counter+ 1 ;
  8. ENDWHILE;
  9. END$$
  10. DELIMITER;


REPEATUNTILL

Java代码 复制代码
  1. DELIMITER$$
  2. DROPPROCEDUREIFEXISTSsimple_repeat$$
  3. CREATEPROCEDUREsimple_repeat(OUTcounterINT)
  4. BEGIN
  5. SETcounter= 0 ;
  6. REPEAT
  7. SETcounter=counter+ 1 ;
  8. UNTILcounter= 10 ENDREPEAT;
  9. END$$
  10. DELIMITER;



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

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

Java代码 复制代码
  1. DECLAREtotal_salesNUMERIC( 8 , 2 );
  2. SELECTSUM(sale_value)INTOtotal_salesFROMsalesWHEREcustomer_id=in_customer_id;



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

Java代码 复制代码
  1. DELIMITER$$
  2. DROPPROCEDUREIFEXITScursor_example$$
  3. CREATEPROCEDUREcursor_example()
  4. READSSQLDATA
  5. BEGIN
  6. DECLAREl_employee_idINT;
  7. DECLAREl_salaryNUMERIC( 8 , 2 );
  8. DECLAREl_department_idINT;
  9. DECLAREdoneINTDEFAULT 0 ;
  10. DECLAREcur1CURSORFORSELECTemployee_id,salary,department_idFROMemployees;
  11. DECLARECONTINUEHANDLERFORNOTFOUNDSETdone= 1 ;
  12. OPENcur1;
  13. emp_loop:LOOP
  14. FETCHcur1INTOl_employee_id,l_salary,l_department_id;
  15. IFdone= 1 THEN
  16. LEAVEemp_loop;
  17. ENDIF;
  18. ENDLOOPemp_loop;
  19. CLOSEcur1;
  20. END$$
  21. DELIMITER;



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

Java代码 复制代码
  1. DELIMITER$$
  2. DROPPROCEDUREIFEXISTSsp_emps_in_dept$$
  3. CREATEPROCEDUREsp_emps_in_dept(in_employee_idINT)
  4. BEGIN
  5. SELECTemployee_id,surname,firstname,address1,address2,zipcode,date_of_birthFROMemployeesWHEREdepartment_id=in_employee_id;
  6. END$$
  7. DELIMITER;



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

Java代码 复制代码
  1. DELIMITER$$
  2. DROPPROCEDUREIFEXITSsp_update_salary$$
  3. CREATEPROCEDUREsp_update_salary(in_employee_idINT,in_new_salaryNUMERIC( 8 , 2 ))
  4. BEGIN
  5. IFin_new_salary< 5000 ORin_new_salary> 500000 THEN
  6. SELECT "Illegalsalary:salarymustbebetween$5000and$500,000" ;
  7. ELSE
  8. UPDATEemployeesSETsalary=in_new_salaryWHEREemployee_id=in_employee_id;
  9. ENDIF:
  10. END$$
  11. DELIMITER;



9,使用CALL 调用存储程序

Java代码 复制代码
  1. DELIMITER$$
  2. DROPPROCEDUREIFEXISTScall_example$$
  3. CREATEPROCEDUREcall_example(employee_idINT,employee_typeVARCHAR( 20 ))
  4. NOSQL
  5. BEGIN
  6. DECLAREl_bonus_amountNUMERIC( 8 , 2 );
  7. IFemployee_type= 'MANAGER' THEN
  8. CALLcalc_manager_bonus(employee_id,l_bonus_amount);
  9. ELSE
  10. CALLcalc_minion_bonus(employee_id,l_bonus_amount);
  11. ENDIF;
  12. CALLgrant_bonus(employee_id,l_bonus_amount);
  13. END$$
  14. DELIMITER;



10,一个复杂的例子

Java代码 复制代码
  1. CREATEPROCEDUREputting_it_all_together(in_department_idINT)
  2. MODIFIESSQLDATA
  3. BEGIN
  4. DECLAREl_employee_idINT;
  5. DECLAREl_salaryNUMERIC( 8 , 2 );
  6. DECLAREl_department_idINT;
  7. DECLAREl_new_salaryNUMERIC( 8 , 2 );
  8. DECLAREdoneINTDEFAULT 0 ;
  9. DECLAREcur1CURSORFOR
  10. SELECTemployee_id,salary,department_id
  11. FROMemployees
  12. WHEREdepartment_id=in_department_id;
  13. DECLARECONTINUEHANDLERFORNOTFOUNDSETdone= 1 ;
  14. CREATETEMPORARYTABLEIFNOTEXISTSemp_raises
  15. (employee_idINT,department_idINT,new_salaryNUMERIC( 8 , 2 ));
  16. OPENcur1;
  17. emp_loop:LOOP
  18. FETCHcur1INTOl_employee_id,l_salary,l_department_id;
  19. IFdone= 1 THEN /*Nomorerows*/
  20. LEAVEemp_loop;
  21. ENDIF;
  22. CALLnew_salary(1_employee_id,l_new_salary); /*Getnewsalary*/
  23. IF(l_new_salary<>l_salary)THEN /*Salarychanged*/
  24. UPDATEemployees
  25. SETsalary=l_new_salary
  26. WHEREemployee_id=l_employee_id;
  27. /*Keeptrackofchangedsalaries*/
  28. INSERTINTOemp_raises(employee_id,department_id,new_salary)
  29. VALUES(l_employee_id,l_department_id,l_new_salary);
  30. ENDIF:
  31. ENDLOOPemp_loop;
  32. CLOSEcur1;
  33. /*Printoutthechangedsalaries*/
  34. SELECTemployee_id,department_id,new_salaryfromemp_raises
  35. ORDERBYemployee_id;
  36. END;



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

Java代码 复制代码
  1. CREATE
  2. [DEFINER={user|CURRENT_USER}]
  3. PROCEDUREsp_name([proc_parameter[,...]])
  4. [characteristic...]routine_body
  5. CREATE
  6. [DEFINER={user|CURRENT_USER}]
  7. FUNCTIONsp_name([func_parameter[,...]])
  8. RETURNStype
  9. [characteristic...]routine_body
  10. proc_parameter:
  11. [IN|OUT|INOUT]param_nametype
  12. func_parameter:
  13. param_nametype
  14. type:
  15. AnyvalidMySQLdatatype
  16. characteristic:
  17. LANGUAGESQL
  18. |[NOT]DETERMINISTIC
  19. |{CONTAINSSQL|NOSQL|READSSQLDATA|MODIFIESSQLDATA}
  20. |SQLSECURITY{DEFINER|INVOKER}
  21. |COMMENT 'string'
  22. routine_body:
  23. ValidSQLprocedurestatement


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

Java代码 复制代码
  1. DELIMITER$$
  2. DROPFUNCTIONIFEXISTSf_discount_price$$
  3. CREATEFUNCTIONf_discount_price
  4. (normal_priceNUMERIC( 8 , 2 ))
  5. RETURNSNUMERIC( 8 , 2 )
  6. DETERMINISTIC
  7. BEGIN
  8. DECLAREdiscount_priceNUMERIC( 8 , 2 );
  9. IF(normal_price> 500 )THEN
  10. SETdiscount_price=normal_price*. 8 ;
  11. ELSEIF(normal_price> 100 )THEN
  12. SETdiscount_price=normal_price*. 9 ;
  13. ELSE
  14. SETdiscount_price=normal_price;
  15. ENDIF;
  16. RETURN(discount_price);
  17. END$$
  18. DELIMITER;



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

Java代码 复制代码
  1. DELIMITER$$
  2. DROPTRIGGERsales_trigger$$
  3. CREATETRIGGERsales_trigger
  4. BEFOREINSERTONsales
  5. FOREACHROW
  6. BEGIN
  7. IFNEW.sale_value> 500 THEN
  8. SETNEW.free_shipping= 'Y' ;
  9. ELSE
  10. SETNEW.free_shipping= 'N' ;
  11. ENDIF;
  12. IFNEW.sale_value> 1000 THEN
  13. SETNEW.discount=NEW.sale_value*. 15 ;
  14. ELSE
  15. SETNEW.discount= 0 ;
  16. ENDIF;
  17. END$$
  18. DELIMITER;

分享到:
评论

相关推荐

    phpmyadmin

    phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库。借由此Web接口可以成为一个简易方式输入繁杂SQL语法的较佳途径,尤其要处理大量资料...

    phpMyAdmin安装配置方法全过程

    phpMyAdmin安装配置方法全过程,自己实验过!很好用的!相信的话可以试试的!

    单文件phpmyadmin,功能强大不比phpmyadmin差

    单文件phpmyadmin,功能强大不比phpmyadmin差,可导出导入。可执行sql语句。

    phpmyAdmin

    通过phpMyAdmin可以完全对数据库进行操作,例如建立、复制/删除数据等等。 管理 MySQL-server 以及单一数据库的 PHP 程序,对于不熟悉 MySQL 命令列指令的人来说, 是很方便的管理工具。 phpMyAdmin功能: 建立、...

    phpMyAdmin修正补丁3.1.1

    phpmyadmin是大家很常用的...导出后因为文档中包含中文,不能用未修下的phpmyadmin进行导入,用命令行导入,请正确设置连接编码。请多次尝试后,再将其用于正式场合。  如遇问题,请及时与本人联系:aaliwen@126.com。

    phpMyAdmin修正补丁3.1.2

    phpmyadmin是大家很常用的...导出后因为文档中包含中文,不能用未修下的phpmyadmin进行导入,用命令行导入,请正确设置连接编码。请多次尝试后,再将其用于正式场合。  如遇问题,请及时与本人联系:aaliwen@126.com。

    phpmyadmin数据库管理工具(图解)

    phpmyadmin数据库管理工具(图解)phpmyadmin数据库管理工具(图解)phpmyadmin数据库管理工具(图解)phpmyadmin数据库管理工具(图解)phpmyadmin数据库管理工具(图解)

    phpMyAdmin安装配置方法全过程,及问题解决.txt

    phpMyAdmin安装配置方法全过程,及问题解决.txt

    phpMyAdmin 4.6.6.zip

    phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库。借由此Web接口可以成为一个简易方式输入繁杂SQL语法的较佳途径,尤其要处理大量资料...

    phpMyAdmin4.8.1

    phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库。借由此Web接口可以成为一个简易方式输入繁杂SQL语法的较佳途径,尤其要处理大量资料...

    phpMyAdmin 4.0.4 官方中文版

    phpMyAdmin是一款运行在服务器上的MySQL数据库管理程序,可以对数据库进行建立/复制/删除/修改数据等等操作,还可以执行SQL脚本。phpMyAdmin基于Web方式运行,下载后解压到网站根目录,然后访问即可远端管理MySQL...

    phpMyadmin2.3

    phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库。借由此Web接口可以成为一个简易方式输入繁杂SQL语法的较佳途径,尤其要处理大量资料...

    phpMyAdmin

    phpMyAdmin - Readme =================== Version 4.3.3 A set of PHP-scripts to manage MySQL over the web. http://www.phpmyadmin.net/ Summary ------- phpMyAdmin is intended to handle the ...

    phpMyAdmin暴力破解v1.3

    1.0版本有个标题问题,正在win7、vista下都不能正常扫描, 现曾纠正过往。 ————————————————— 技术总结: 《vc6建正删除cookie真现》 InternetSetCookie函数太老,能建正一般cookie值,但是正在win...

    phpmyadmin 正式版

    phpMyAdmin是一个用PHP编写的,可以通过互联网控制和操作MySQL。通过phpMyAdmin可以完全对数据库进行操作,例如建立、复制/删除数据等等。

    phpMyAdmin v3.5.0 For Linux

    通过 phpMyAdmin 可以完全对数据库进行操作,例如建立、复制、删除数据等等。如果使用合适的工具,MySQL 数据库的管理就会变得相当简单。应用 MySQL 命令行方式需要对 MySQL 知识非常熟悉,对 SQL语言也是同样的道理...

    phpMyAdmin v4.8.5.zip

    phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库。借由此Web接口可以成为一个简易方式输入繁杂SQL语法的较佳途径,尤其要处理大量资料...

    phpMyAdmin多线程批量破解工具

    phpMyAdmin多线程批量破解工具是一款用于数据库密码强制破解的工具,了解它的朋友想必不用做过多的介绍就应该了解他他是做什么的。 之前朋友问我有木有phpMyAdmin批量破解工具, 我在网上搜索了一下并没有发现相关的...

Global site tag (gtag.js) - Google Analytics