TSQL 使用存储过程

来源:互联网 发布:linux mysql 卸载 编辑:程序博客网 时间:2024/05/04 05:53

使用存储过程

简单的老的jdbc通过callablestatement类支持存储过程的调用。
该类实际上是preparedstatement的一个子类。
假设我们有一个poets数据库。数据库中有一个设置诗人逝世年龄的存储过程。
下面是对老酒鬼dylan thomas(old soak dylan thomas
不指定是否有关典故、文化,请批评指正。译注)进行调用的详细代码:

try{
int age = 39;

string poetname = "dylan thomas";

callablestatement proc = connection.preparecall("{ call set_death_age(?, ?) }");

proc.setstring(1, poetname);

proc.setint(2, age);

cs.execute();

}catch (sqlexception e){ // ....}

传给preparecall方法的字串是存储过程调用的书写规范。它指定了存储过程的名称,
?代表了你需要指定的参数。

 

 


将这些sql语句转移到一个存储过程中将大大简化代码,仅涉及一次网络调用。
所有关联的sql操作都可以在数据库内部发生。并且,存储过程语言,例如pl/sql,
允许使用sql语法,这比java代码更加自然。下面是我们早期的存储过程,
使用oracle的pl/sql语言编写:

create procedure set_death_age(poet varchar2, poet_age number)

poet_id number;

begin select id into poet_id from poets where name = poet;

insert into deaths (mort_id, age) values (poet_id, poet_age);

end set_death_age;

很独特?不。我打赌你一定期待看到一个poets表上的update。
这也暗示了使用存储过程实现是多么容易的一件事情。
set_death_age几乎可以肯定是一个很烂的实现。
我们应该在poets表中添加一列来存储逝世年龄。
java代码中并不关心数据库模式是怎么实现的,因为它仅调用存储过程。
我们以后可以改变数据库模式以提高性能,但是我们不必修改我们代码。
下面是调用上面存储过程的java代码:

public static void setdeathage(poet dyingbard, int age) throws sqlexception{

connection con = null;

callablestatement proc = null;

try {

con = connectionpool.getconnection();

proc = con.preparecall("{ call set_death_age(?, ?) }");

proc.setstring(1, dyingbard.getname());

proc.setint(2, age);

proc.execute();

}

finally {

try { proc.close(); }

catch (sqlexception e) {}

con.close();

}

}

为了确保可维护性,建议使用像这儿这样的static方法。
这也使得调用存储过程的代码集中在一个简单的模版代码中。
如果你用到许多存储过程,就会发现仅需要拷贝、粘贴就可以创建新的方法。
因为代码的模版化,甚至也可以通过脚本自动生产调用存储过程的代码。

functions

存储过程可以有返回值,所以callablestatement类有类似getresultset这样的方法来获取返回值。
当存储过程返回一个值时,你必须使用registeroutparameter方法告诉jdbc驱动器该值的sql类型是什么。
你也必须调整存储过程调用来指示该过程返回一个值。
下面接着上面的例子。这次我们查询dylan thomas逝世时的年龄。这次的存储过程使用postgresql的pl/pgsql:

create function snuffed_it_when (varchar) returns integer declare

poet_id number;

poet_age number;

begin

--first get the id associated with the poet.

select id into poet_id from poets where name = $1;

--get and return the age.

select age into poet_age from deaths where mort_id = poet_id;

return age;

end; language pl/pgsql;

另外,注意pl/pgsql参数名通过unix和dos脚本的$n语法引用。同时,也注意嵌入的注释,
这是和java代码相比的另一个优越性。在java中写这样的注释当然是可以的,但是看起来很凌乱,
并且和sql语句脱节,必须嵌入到java string中。
下面是调用这个存储过程的java代码:

connection.setautocommit(false);

callablestatement proc = connection.preparecall("{ ? = call snuffed_it_when(?) }");

proc.registeroutparameter(1, types.integer);

proc.setstring(2, poetname);

cs.execute();

int age = proc.getint(2);

如果指定了错误的返回值类型会怎样?那么,当调用存储过程时将抛出一个runtimeexception,
正如你在resultset操作中使用了一个错误的类型所碰到的一样。

 

原创粉丝点击