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。