呼叫PostgreSQL儲存過程,找不到函式名的問題
PostgreSQL的表,函式名稱都是嚴格區分大小寫的,所以在使用的時候沒有注意大小寫問題容易導致找不到函式名的錯誤,但最近兩天我們發現,如果函式引數使用了自定義的資料型別,也會發生這個問題。
問題描述:
下面的示例測試程式碼:
PWMIS.DataProvider.Data.AdoHelper db = MyDB.GetDBHelperByConnectionName("PostgreSQL"); IDataParameter para = db.GetParameter(); para.ParameterName = "@jjdm"; para.DbType = DbType.AnsiString ; para.Value = "KF0355"; int count= db.ExecuteNonQuery("updatefundattention", System.Data.CommandType.StoredProcedure, new System.Data.IDataParameter[] { para });
執行該儲存過程,出現下面的錯誤:
DataBase ErrorMessage:ERROR: 42883: function updatefundattention(text) does not exist SQL:updatefundattention CommandType:StoredProcedure Parameters: Parameter["@jjdm"] = "KF0355" //DbType=String
實際上,PostgreSQL的函式updatefundattention 引數型別不是 text,而是自定義的型別 citex ,下面是函式定義:
CREATE OR REPLACE FUNCTION updatefundattention(jjdm citext) RETURNS void AS $BODY$ DECLARE BEGIN update JJZB set gzd=COALESCE(gzd,0)+1 where JJZB.Jjdm=$1 ; --return 1; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; ALTER FUNCTION updatefundattention(citext) OWNER TO postgres;
昨天分析可能PostgreSQL的字元型引數不能使用AnsiString引數型別,需要使用String型別,但今天測試發現
para.DbType = DbType.String ;
問題依然沒有解決。
重新建立一個測試函式updatefundattention,只是引數型別為 varchar:
CREATE OR REPLACE FUNCTION updatefundattention2(jjdm character varying) RETURNS void AS $BODY$ DECLARE BEGIN update JJZB set gzd=COALESCE(gzd,0)+1 where JJZB.Jjdm=$1 ; --return 1; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; ALTER FUNCTION updatefundattention2(character varying) OWNER TO postgres;
執行測試程式,不論
para.DbType = DbType.AnsiString ;
還是
para.DbType = DbType.String ;
呼叫函式updatefundattention2 均能通過,故此得到結論:
目前自定義的 citext 型別.NET程式無法設定正確的DbType,從而會出現找不到函式的錯誤!
問題影響:
在WFT中,所有使用.NET程式呼叫PostgreSQL儲存過程的程式碼,如果儲存過程的引數使用了自定義的型別(例如citex),均會受影響。
解決方案:
a,建議不要在PostgreSQL函式的引數中使用自定義的型別,如果要想對引數進行大小寫轉換,建議在函式體中使用另外一個Pgsql變數,函式中執行查詢的SQL語句使用這個新變數,而不是直接使用這個函式引數;
b,修改Sql-Map中的SQL語句,例如
<Select CommandName="AddGuanZhuDu" Method="" CommandType="StoredProcedure" Description="增加關注度" ResultClass="ValueType"><![CDATA[
UpdateFundAttention
#jjdm : String#
]]></Select>
修改成下面的方式:
<Select CommandName="AddGuanZhuDu" Method="" CommandType="Text" Description="增加關注度" ResultClass="ValueType"><![CDATA[
select * from UpdateFundAttention (#jjdm: String#)
]]></Select>
但這種修改方式會造成SqlServer與PostgreSQL的SQL-MAP語句不相同,增加程式的維護量,理想的方式是SQL-MAP語句儘量相同。