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。