MFC中和libpq調用PostgreSQL存儲過程需要注意的問題

1、 用MFC以ADO方式連接PostgreSQL數據庫,調用PostgreSQL數據庫的存儲過程。簡略代碼爲:

_ConnectionPtr pconnection = theApp.getdbconnection();

_RecordsetPtr pPtr;
if (FAILED( pPtr.CreateInstance( __uuidof(Recordset) )))
{
  return -5;
}

CString strSQL;
strSQL.Format( _T("select * from /"funCheckLogin/"( '%s', '%s' )"), m_szLoginName, m_szLoginPwd );

_variant_t varSQL(strSQL);
HRESULT hr = S_FALSE;
try
{
  hr = pPtr->Open( varSQL,_variant_t((IDispatch*)pconnection,true),adOpenStatic,adLockOptimistic,adCmdText);
}

其中存儲過程"funCheckLogin"返回的是記錄集SETOF形式,用該種方式調用存儲過程時,結果都正常,只是在PostgreSQL的Log中會有

2008-08-05 16:29:46 HKT ERROR:  relation "funCheckLogin" does not exist
2008-08-05 16:29:46 HKT STATEMENT:  select nspname from pg_namespace n, pg_class c where c.relnamespace=n.oid and c.oid='"funCheckLogin"'::regclass

這樣的Error錯誤顯示,雖然不影響正常使用,但畢竟有錯誤發生。

若"funCheckLogin"返回一列一行的形式,比如返回int或varchar等等,調用時使用

strSQL.Format( _T("select  /"funCheckLogin/"( '%s', '%s' )"), m_szLoginName, m_szLoginPwd );

hr = pPtr->Open( varSQL,_variant_t((IDispatch*)pconnection,true),adOpenStatic,adLockOptimistic,adCmdText);

這樣也沒有LOG錯誤,究其原因是,select * from後在PostgreSQL中是以查詢表的方式存在,而數據庫中並沒有"funCheckLogin"這個表,因此會出現Error。改正方式如下:

(1)若在pgAdmin中可以用select  /"funCheckLogin/"( '%s', '%s' )的形式,則

strSQL.Format( _T("select  /"funCheckLogin/"( '%s', '%s' )"), m_szLoginName, m_szLoginPwd );

hr = pPtr->Open( varSQL,_variant_t((IDispatch*)pconnection,true),adOpenStatic,adLockOptimistic,adCmdText);

可以正常使用。

(2)若在pgAdmin中必須用select * from存儲過程的形式(如返回SETOF),則可以修改VC中的調用方式:

strSQL.Format( _T(" /"funCheckLogin/"( '%s', '%s' )"), m_szLoginName, m_szLoginPwd );

hr = pPtr->Open( varSQL,_variant_t((IDispatch*)pconnection,true),adOpenStatic,adLockOptimistic,adCmdStoreProc);

其實方式(2)纔是調用存儲過程比較合理的方式。

 

2、Linux下在Libpq中調用PostgreSQL的存儲過程,若存儲過程返回遊標的形式,比如:

CREATE OR REPLACE FUNCTION "funSelectScenarioElementBySid"(REFCURSOR,Sid INT)
RETURNS REFCURSOR AS
$$
BEGIN
OPEN $1 FOR
SELECT "SEid","SEindex","SEcontent","SEsynthesis","SEdlgelement","SEbranchCondition","SErepeatedly","SEtbname","SEfieldname","SEtargetname"
FROM
 "ScenarioElement"
WHERE
 "Sid" = Sid
ORDER BY "SEid";
RETURN $1;
END
$$
LANGUAGE PLPGSQL;

--BEGIN
--SELECT "funSelectScenarioElementBySid"('A',2)
--FETCH ALL IN "A"
--END

在該種形式下,在libpg中是不需要執行

res = PQexec(conn, "CLOSE myportal");
PQclear(res);

否則,會在數據庫服務器的LOG中寫入錯誤,如下:

ERROR:  34000: cursor "recordcur" does not exist
LOCATION:  PerformPortalClose, portalcmds.c:236
STATEMENT:  CLOSE recordcur。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章