因為工作的地方是用M$系列的,所以之前部門的開發就是用M$SQL的預儲程式(stored procedure)來執行與資料的讀取的動作,說真的,超不習慣的啦!雖然他們的立場是覺得stored procedure可以重複利用,可是我覺得這跟直接把SQL用刻在php程式碼裡,良好的設計(指物件寫法),也是可以重複利用呀,而且PHP可以用的函式又多,要去刻SQL也方便多了。如果硬是要說stored procedure好處,可能就是效能加快,安全性上升(有差那麼多嗎?個人不覺得)。
anyway...畢竟在工作的地方就是配合大家,所以我從google大仙去搜尋如何用PEAR::DB來呼叫已經寫好的預儲程式,不過相當殘念的,似乎這種文件非常少(>"Programming with SQL Relay using the PHP Pear DB API」。這篇文章把PEAR::DB所有連結資料庫與執行SQL的部分,做了滿多的範例,以下我就直接針對預儲程式的部分來說明(接下來的程式都是從文章擷錄而來)
Oracle作法
首頁先建立一個預儲程式如下
create procedure testproc(in1 in number, in2 in number, in3 in varchar2) is begin insert into mytable values (in1,in2,in3); end;
接下來直接用PEAR執行指定的預儲程式,並給予參數
$sth=$db->prepare("begin testproc(:in1,:in2,:in3); end;"); $bindvars=array("in1" => 1, "in2" => 1.1, "in3" => "hello"}) $res=$db->execute($sth,$bindvars);
Sybase與Microsoft SQL Server作法
首頁先建立一個預儲程式如下
create procedure testproc @in1 int, @in2 float, @in3 varchar(20) as insert into mytable values (@in1,@in2,@in3)
接下來直接用PEAR執行指定的預儲程式,並給予參數
$sth=$db->prepare("exec testproc"); $bindvars=array("in1" => 1, "in2" => 1.1, "in3" => "hello"}) $res=$db->execute($sth,$bindvars);
Postgresql的作法
首頁先建立一個預儲程式如下
create function testproc(int,float,varchar(20)) returns void as begin insert into mytable values ($1,$2,$3); return; end;
接下來直接用PEAR執行指定的預儲程式,並給予參數
$res=$db->prepare("select testproc(:in1,:in2,:in3)"); $bindvars=array("in1" => 1, "in2" => 1.1, "in3" => "hello"}) $res=$db->execute($res,$bindvars);
DB2的作法
首頁先建立一個預儲程式如下
create procedure testproc(in in1 int, in in2 double, in in3 varchar(20)) begin insert into mytable values (in1,in2,in3); end;
接下來直接用PEAR執行指定的預儲程式,並給予參數
$sth=$db->prepare("call testproc(?,?,?)"); $bindvars=array("1" => 1, "2" => 1.1, "3" => "hello"}) $res=$db->execute($sth,$bindvars);
嗯…最後我就選用了MSSQL方法,不過結果竟然無效!!囧rz...。說真的我也不知道原因在哪,可是是PEAR::DB版本有更新吧,而且我又是外掛DB_odbtp去連MSSQL的,所以可能有些小問題,所以我最後改寫能跑的程式碼如下:
/******************************** * 使用範例 ********************************/ //指定執行的stored procedure與傳送的參數 $sth= $db->prepare("exec testproc @sDataType = ?,@beginNum = ?"); //建立參數 $params = array('Ver',0,0); //檢查預儲程式是否有錯誤 if (PEAR::isError($sth)) { die('prepare error:'.$sth->getMessage()); } //執行含有參數的預儲程式 $res = $db->execute($sth,$params); //檢查執行是否有錯誤 if (PEAR::isError($res)) { if($res->getMessage() == 'DB Error: unknown error'){ die('execute error:'.$res->userinfo); } else { die('execute error:'.$res->getMessage()); } } //讀取內容 while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) { echo $row['Version'] . "\n"; }