MySQL存储过程
2014-02-25 21:43
344 查看
1.1CREATEPROCEDURE(创建)
CREATEPROCEDURE存储过程名(参数列表) BEGIN SQL语句代码块 END |
注意:
由括号包围的参数列必须总是存在。如果没有参数,也该使用一个空参数列()。每个参数默认都是一个IN参数。要指定为其它参数,可在参数名之前使用关键词OUT或INOUT
在mysql客户端定义存储过程的时候使用delimiter命令来把语句定界符从;变为//。
当使用delimiter命令时,你应该避免使用反斜杠(‘"’)字符,因为那是MySQL的转义字符。
如:
mysql>delimiter// mysql>CREATEPROCEDUREsimpleproc(OUTparam1INT) ->BEGIN ->SELECTCOUNT(*)INTOparam1FROMt; ->END ->// QueryOK,0rowsaffected(0.00sec) |
mysql>CALLsimpleproc(@a);
QueryOK,0rowsaffected(0.00sec)
mysql>SELECT@a;
+------+
|@a|
+------+
|3|
+------+
1rowinset(0.00sec))
SELECT...INTOselectscolumnvaluesandstoresthemintovariables.var_list
[code]SELECT...INTOOUTFILEwritestheselectedrowstoafile.Columnandlineterminatorscanbespecifiedtoproduceaspecificoutputformat.
SELECT...INTODUMPFILEwritesasinglerowtoafilewithoutanyformatting.)
@a什么意思?
9.3.用户变量
可以先在用户变量中保存值然后在以后引用它;这样可以将值从一个语句传递到另一个语句。用户变量与连接有关。也就是说,一个客户端定义的变量不能被其它客户端看到或使用。当客户端退出时,该客户端连接的所有变量将自动释放。
用户变量的形式为@var_name,其中变量名var_name可以由当前字符集的文字数字字符、‘.’、‘_’和‘$’组成。默认字符集是cp1252(Latin1)。可以用mysqld的--default-character-set选项更改字符集。参见5.10.1节,“数据和排序用字符集”。用户变量名对大小写不敏感。
设置用户变量的一个途径是执行SET语句:
SET@var_name=expr[,@var_name=expr]...对于SET,可以使用=或:=作为分配符。分配给每个变量的expr可以为整数、实数、字符串或者NULL值。
也可以用语句代替SET来为用户变量分配一个值。在这种情况下,分配符必须为:=而不能用=,因为在非SET语句中=被视为一个比较操作符:
mysql>SET@t1=0,@t2=0,@t3=0;mysql>SELECT@t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;+----------------------+------+------+------+|@t1:=(@t2:=1)+@t3:=4|@t1|@t2|@t3|+----------------------+------+------+------+|5|5|1|4|+----------------------+------+------+------+用户变量可以用于表达式中。目前不包括明显需要文字值的上下文中,例如SELECT语句的LIMIT子句,或者LOADDATA语句的IGNOREnumberLINES子句。
如果使用没有初始化的变量,其值是NULL。
1.2ALTERPROCEDURE(修改)
ALTERPROCEDURE存储过程名SQL语句代码块 |
这个语句可以被用来改变一个存储程序的特征。
1.3DROPPROCEDURE(删除)
DROPPROCEDUREIFEXISTS存储过程名 eg:DROPPROCEDUREIFEXISTSproc_employee(proc_employee存储过程名) |
这个语句被用来移除一个存储程序。不能在一个存储过程中删除另一个存储过程,只能调用另一个存储过程
1.4SHOWCREATEPROCEDURE(类似于SHOWCREATETABLE,查看一个已存在的存储过程)
SHOWCREATEPROCEDURE存储过程名 |
1.5SHOWPROCEDURESTATUS(列出所有的存储过程)
SHOWPROCEDURESTATUS |
1.6CALL语句(存储过程的调用)
CALL存储过程名(参数列表) |
CALL语句调用一个先前用CREATEPROCEDURE创建的程序。
CALL语句可以用声明为OUT或的INOUT参数的参数给它的调用者传回值。
存储过程名称后面必须加括号,哪怕该存储过程没有参数传递
1.7BEGIN...END(复合语句)
[begin_label:] BEGIN [statement_list] END [end_label] |
statement_list代表一个或多个语句的列表。statement_list之内每个语句都必须用分号(;)来结尾。
复合语句可以被标记。除非begin_label存在,否则end_label不能被给出,并且如果二者都存在,他们必须是同样的。
1.8DECLARE语句(用来声明局部变量)
DECLARE语句被用来把不同项目局域到一个子程序:局部变量DECLARE仅被用在BEGIN...END复合语句里,并且必须在复合语句的开头,在任何其它语句之前。
1.9存储程序中的变量
1.1DECLARE局部变量DECLAREvar_name[,...]type[DEFAULTvalue] 这个语句被用来声明局部变量。 要给变量提供一个默认值,请包含一个DEFAULT子句。 值可以被指定为一个表达式,不需要为一个常数。 如果没有DEFAULT子句,初始值为NULL。 局部变量的作用范围在它被声明的BEGIN...END块内。 它可以被用在嵌套的块中,除了那些用相同名字声明变量的块。 |
SETvar_name=expr[,var_name=expr] 在存储程序中的SET语句是一般SET语句的扩展版本。 被参考变量可能是子程序内声明的变量,或者是全局服务器变量。 在存储程序中的SET语句作为预先存在的SET语法的一部分来实现。这允许SETa=x,b=y,...这样的扩展语法。 其中不同的变量类型(局域声明变量及全局和集体变量)可以被混合起来。 这也允许把局部变量和一些只对系统变量有意义的选项合并起来。 |
SELECTcol_name[,...]INTOvar_name[,...]table_expr 这个SELECT语法把选定的列直接存储到变量。 因此,只有单一的行可以被取回。 SELECTid,dataINTOx,yFROMtest.t1LIMIT1; 注意,用户变量名在MySQL5.1中是对大小写不敏感的。 |
1.10MySQL存储过程参数类型(in、out、inout)
此小节内容来自:参见地址:http://www.blogjava.net/nonels/archive/2009/04/22/233324.html
MySQL存储过程参数(in)
MySQL存储过程“in”参数:跟C语言的函数参数的值传递类似,MySQL存储过程内部可能会修改此参数,但对in类型参数的修改,对调用者(caller)来说是不可见的(notvisible)。 |
MySQL存储过程“out”参数:从存储过程内部传值给调用者。在存储过程内部,该参数初始值为null,无论调用者是否给存储过程参数设置值 |
MySQL存储过程inout参数跟out类似,都可以从存储过程内部传值给调用者。不同的是:调用者还可以通过inout参数传递值给存储过程。 |
如果仅仅想把数据传给MySQL存储过程,那就使用“in”类型参数;如果仅仅从MySQL存储过程返回值,那就使用“out”类型参数;如果需要把数据传给MySQL存储过程,还要经过一些计算后再传回给我们,此时,要使用“inout”类型参数。 |
1.11例子:
1.1创建存储过程带(输出参数)返回值的存储过程:
--删除存储过程 DROPPROCEDUREIFEXISTSproc_employee_getCount --创建存储过程 CREATEPROCEDUREproc_employee_getCount(outnint) BEGIN SELECTCOUNT(*)FROMemployee; END --MYSQL调用存储过程 CALLproc_employee_getCount(@n); |
--删除存储过程 DROPPROCEDUREIFEXISTSproc_employee_findById; --创建存储过程 CREATEPROCEDUREproc_employee_findById(innint) BEGIN SELECT*FROMemployeewhereid=n; END --定义变量 SET@n=1; --调用存储过程 CALLproc_employee_findById(@n); |
1.删除存储过程时只需要指定存储过程名即可,不带括号;
2.创建存储过程时,不管该存储过程有无参数,都需要带括号;
3.在使用SET定义变量时应遵循SET的语法规则;
SET@变量名=初始值;
4.在定义存储过程参数列表时,应注意参数名与数据库中字段名区别开来,否则将出现无法预期的结果
1.12Java代码调用存储过程(JDBC)
相关API:java.sql.CallableStatement使用到java.sql.CallableStatement接口,该接口专门用来调用存储过程;
该对象的获得依赖于java.sql.Connection;
通过Connection实例的prepareCall()方法返回CallableStatement对象
prepareCall()内部为一固定写法{call存储过程名(参数列表1,参数列表2)}可用?占位
eg:connection.prepareCall("{callproc_employee(?)}");
存储过程中参数处理:
输入参数:通过java.sql.CallableStatement实例的setXXX()方法赋值,用法等同于java.sql.PreparedStatement
输出参数:通过java.sql.CallableStatement实例的registerOutParameter(参数位置,参数类型)方法赋值,其中参数类型主要使用java.sql.Types中定义的类型
Java代码调用带输入参数的存储过程(根据输入ID查询雇员信息)
publicvoidexecuteProcedure() { try{ /** *callableStatementjava.sql.CallableStatement *connectionjava.sql.Connection *jdbc调用存储过程原型 *{call存储过程名(参数列表1,参数列表2)}可用?代替 */ callableStatement=connection.prepareCall("{callproc_employee_findById(?)}"); callableStatement.setInt(1,1);//设置输入参数 resultSet=callableStatement.executeQuery();//执行存储过程 if(resultSet.next()) { System.out.println(resultSet.getInt(1)+""t"+resultSet.getString(2)); } }catch(SQLExceptione){ e.printStackTrace(); } } |
publicvoidexecuteProcedure() { try{ /** *callableStatementjava.sql.CallableStatement *connectionjava.sql.Connection *jdbc调用存储过程原型 *{call存储过程名(参数列表1,参数列表2)}可用?代替 */ callableStatement=connection.prepareCall("{callproc_employee_getCount(?)}"); //设置输出参数 callableStatement.registerOutParameter(1,Types.INTEGER); //执行存储过程 resultSet=callableStatement.executeQuery(); if(resultSet.next()) { System.out.println(resultSet.getInt(1)); } }catch(SQLExceptione){ e.printStackTrace(); } } |
1.13声明:
此文档中除MySQL存储过程参数类型(in、out、inout)小节来自网上,其余均为本人原创,欢迎大家转载,如有不足,请指教。由于是在word中编辑好拷贝过来的所以字体较小大家点此
上面转自:
存储过程示例:
BEGIN
#Roudecntinebodygoeshere...
declarenint;
setn=1;
whilen<=10
do
insertintouser(username,password)value(concat('user',n),concat('pwd',n));
setn=n+1;
endwhile;
END
注意;号的使用。
mysql存储过程中用变量做表名
首先要知道的是,表名createtabletableName,这个tablename不是字符串,你试试用字符串运行就知道报错了。mysql存储过程中用变量做表名
1.用变量做表名:
简单的用set或者declare语句定义变量,然后直接作为sql的表名是不行的,mysql会把变量名当作表名。在其他的sql
这在
Sql代码
PREPAREstmt_nameFROMpreparable_stmt;
EXECUTEstmt_name[USING@var_name[,@var_name]...];
{DEALLOCATE|DROP}PREPAREstmt_name;
MySQLprepare语法:
PREPAREstatement_nameFROMpreparable_SQL_statement;/*定义*/
EXECUTEstatement_name[USING@var_name[,@var_name]...];/*执行预处理语句*/
{DEALLOCATE|DROP}PREPAREstatement_name/*删除定义*/;
PREPARE语句用于预备一个语句,并指定名称statement_name,以后引用该语句。语句名称对大小写不敏感。preparable_stmt可以是一个文字字符串,也可以是一个包含了语句文本的用户变量。该文本必须表现为一个单一的SQL语句,而不是多个语句。在这语句里,‘?'字符可以被用于标识参数,当执行时,以指示数据值绑定到查询后。‘?'字符不应加引号,即使你想要把它们与字符串值结合在一起。参数标记只能用于数据值应该出现的地方,而不是SQL关键字,标识符,等等。
如果预语句已经存在,则在新的预语句被定义前,它会被隐含地删掉。
为了有一个感性的认识,
下面先给几个小例子:
Sql代码
mysql>PREPAREstmt1FROM'SELECTSQRT(POW(?,2)+POW(?,2))AShypotenuse';
mysql>SET@a=3;
mysql>SET@b=4;
mysql>EXECUTEstmt1USING@a,@b;
+------------+
|hypotenuse|
+------------+
|5|
+------------+
mysql>DEALLOCATEPREPAREstmt1;
mysql>SET@s='SELECTSQRT(POW(?,2)+POW(?,2))AShypotenuse';
mysql>PREPAREstmt2FROM@s;
mysql>SET@a=6;
mysql>SET@b=8;
mysql>EXECUTEstmt2USING@a,@b;
+------------+
|hypotenuse|
+------------+
|10|
+------------+
mysql>DEALLOCATEPREPAREstmt2;
如果你的MySQL版本是5.0.7或者更高的,你还可以在LIMIT子句中使用它,示例如下:
Sql代码
mysql>SET@a=1;mysql>PREPARESTMTFROM"SELECT*FROMtblLIMIT?";
mysql>EXECUTESTMTUSING@a;
mysql>SET@skip=1;SET@numrows=5;
mysql>PREPARESTMTFROM"SELECT*FROMtblLIMIT?,?";
mysql>EXECUTESTMTUSING@skip,@numrows;
使用PREPARE的几个注意点:
A:PREPAREstmt_nameFROMpreparable_stmt;预定义一个语句,并将它赋给stmt_name,tmt_name是不区分大小写的。
B:即使preparable_stmt语句中的?所代表的是一个字符串,你也不需要将?用引号包含起来。
C:如果新的PREPARE语句使用了一个已存在的stmt_name,那么原有的将被立即释放!即使这个新的PREPARE语句因为错误而不能被正确执行。
D:PREPAREstmt_name的作用域是当前客户端连接会话可见。
E:要释放一个预定义语句的资源,可以使用DEALLOCATEPREPARE句法。
F:EXECUTEstmt_name句法中,如果stmt_name不存在,将会引发一个错误。
G:如果在终止客户端连接会话时,没有显式地调用DEALLOCATEPREPARE句法释放资源,服务器端会自己动释放它。
H:在预定义语句中,CREATETABLE,DELETE,DO,INSERT,REPLACE,SELECT,SET,UPDATE,和大部分的SHOW句法被支持。
I:PREPARE语句不可以用于存储过程,自定义函数!但从MySQL5.0.13开始,它可以被用于存储过程,仍不支持在函数中使用!
下面给个示例:
Sql代码
CREATEPROCEDURE`p1`(INidINTUNSIGNED,INnameVARCHAR(11))
BEGINlable_exit:
BEGIN
SET@SqlCmd='SELECT*FROMtA';
IFidISNOTNULLTHENSET@SqlCmd=CONCAT(@SqlCmd,'WHEREid=?');
PREPAREstmtFROM@SqlCmd;SET@a=id;
EXECUTEstmtUSING@a;
LEAVElable_exit;
ENDIF;
IFnameISNOTNULLTHENSET@SqlCmd=CONCAT(@SqlCmd,'WHEREnameLIKE?');
PREPAREstmtFROM@SqlCmd;
SET@a=CONCAT(name,'%');
EXECUTEstmtUSING@a;
LEAVElable_exit;
ENDIF;
ENDlable_exit;
END;
CALL`p1`(1,NULL);
CALL`p1`(NULL,'QQ');
DROPPROCEDURE`p1`;
了解了PREPARE的用法,再用变量做表名就很容易了。不过在实际操作过程中还发现其他一些问题,比如变量定义,declare变量和set@var=value变量的用法以及参数传入的变量。
测试后发现,set@var=value这样定义的变量直接写在字符串中就会被当作变量转换,declare的变量和参数传入的变量则必须用CONCAT来连接。具体的原理没有研究。
EXECUTEstmtUSING@a;这样的语句USING后面的变量也只能用set@var=value这种,declare和参数传入的变量不行。
另外php调用mysql存储过程的时候也碰到很多问题,总是出现PROCEDUREpcan'treturnaresultsetinthegivencontext这样的问题。
返回字符串str,左填充len个字符的长度的字符串padstr。如果str的长度大于len,则返回值被缩短至len个字符。
SQL>SELECTLPAD('hi',4,'??');
+---------------------------------------------------------+
|LPAD('hi',4,'??')|
mysql存储过程动态创建表名
set@tablename='tt';
set@sql=concat('select*from',@tablename);
prepareddfrom@sql;
executedd;
例如:
BEGIN
#Routinebodygoeshere...
set@n=1;
while@n<=12
do
set@c=concat('log2016',LPAD(@n,2,'0'));
set@sql=concat("CREATETABLE",@c,"(
`id`int(10)unsignedNOTNULLAUTO_INCREMENT,
`date`datetimeNOTNULL
PRIMARYKEY(`id`)
)ENGINE=MyISAMAUTO_INCREMENT=243DEFAULTCHARSET=utf8
");
PREPAREstmtfrom@sql;
executestmt;
set@n=@n+1;
endwhile;
END
执行就会创建log201601,log201602,一直到Log201612的表。
http://blog.csdn.net/super_ufo/article/details/11215795
相关文章推荐
- mysql explain 中key_len的计算
- mysql基本数据类型(mysql学习笔记三)
- mysql字段类型范围说明:int、bigint、smallint、tinyint,char、varchar、nvarchar
- hibernate与mysql映射类型对应表与mysql导入导出
- mysql 禁制远程连接
- mysql 随机选择一条记录
- mysql全文索引笔记1
- mysql 5.5安装手记
- MySQL必知必会之5-9
- MySQL必知必会之1-4
- MySQL解决抓取文章的html标签替换及其mysql函数的用法说明
- 启动、停止、连接、断开MySQL服务器
- MySQL 常用命令
- mysql创建单个和联合索引
- 写 mysql配置参数 ing
- MySQL常用命令
- mysql实现高效分页
- mysql 语法积累
- mysql 按年度、季度、月度、周、日SQL统计查询
- mysql的一个日常用法的BUG