调用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语句尽量相同。

时间: 2024-10-14 04:03:39

调用PostgreSQL存储过程,找不到函数名的问题的相关文章

Mybatis调用PostgreSQL存储过程实现数组入参传递

注:本文来源于 < Mybatis调用PostgreSQL存储过程实现数组入参传递  > 前言 项目中用到了Mybatis调用PostgreSQL存储过程(自定义函数)相关操作,由于PostgreSQL自带数组类型,所以有一个自定义函数的入参就是一个int数组,形如: CREATE OR REPLACE FUNCTION "public"."func_arr_update"(ids _int4)... 1 如上所示,参数是一个int数组,Mybatis提

对于函数名本质的一点思考

自己在学习函数指针的时候对函数名的意义产生了一点疑惑,经过一些尝试和思考,感觉应该可以像下面这样理解,如果有啥不对的希望大家指正. 首先 我们对变量名的定义做一下回顾: 在C语言里面,我们声明一个变量的时候就会给这个变量名分配一个内存空间,也就是说变量名和内存空间相对应:同时每个内存空间都会有个地址. int a; a=5; 上面两句话说明了:变量a对应的内存空间存储了一个整型数5,并且我们还可以知道这个内存空间的地址是&a. 对于函数的调用我们一般是直接用函数名的,但是在汇编语言里面,调用函数

函数名,闭包,装饰器

#输出的__closure__有cell元素 :是闭包函数 def func(): name = 'eva' def inner(): print(name) print(inner.__closure__) return inner f = func() f() #输出的__closure__为None :不是闭包函数 name = 'egon' def func2(): def inner(): print(name) print(inner.__closure__) return inne

如何使用 JDBC 调用存储在数据库中的函数或存储过程

JDBC调用存储过程步骤:1 通过Connection对象的prepareCall()方法创建一个CallableStatement对象的实例.在使用Connection对象的prepareCall()方法时,需要传入一个String类型的字符串,该字符串用于指明如何调用存储过程{?= call <procedure-name>[(<arg1>,<arg2>, ...)]} {call <procedure-name>[(<arg1>,<a

Delphi 调用C/C++的Dll(stdcall关键字, 会导致函数名分裂. 此时函数名变成[email&#160;protected])

delphi调用C++写的Dll, 当然这个Dll要求是非MFC的Dll, 这样子才能被delphi调用. 根据C++定义函数的情况, Delphi有不同的相对应的处理方法.1. 声明中不加__stdcall,采用VC默认格式__cdecl,但在Delphi中要注明调用格式为cdecl.C++中例子: [cpp] view plain copy print? extern "C" int __declspec(dllexport) add(int x, int y); Delphi中例

python 获取当前调用函数名等log信息

import sys funcName = sys._getframe().f_back.f_code.co_name #获取调用函数名 lineNumber = sys._getframe().f_back.f_lineno #获取行号 print sys._getframe().f_code.co_name # 获取当前函数名 import inspect def get_current_function_name(): return inspect.stack()[1][3] class

python 用字符串调用函数名

方法暂时看到两种: ①eval: def a():     print '1' func_a = 'a' eval(func_a)() 结果:1 ②.vars: 获取当前环境中的全部变量. def a():     print '1' func_a = 'a' vars()[func_a]() 结果:1 对于多个函数统一管理的时候,上面两种写法比较方便,可以直接通过管理函数名变量,来直接控制函数的调用. 比如: def a():     print '1'      def b():     p

Python如何获取到当前函数名和通过字符串调用函数

获取当前函数名: 应用环境: 某些时候, 为了简化和更好扩展程序,我们需要获取到当前运行的函数名字 方法1(不推荐) import sys def I_want_to_know_my_name(): print(sys._getframe().f_code.co_name) #你懂得,下划线开头的不应该使用的 方法2 import traceback def who_am_i(): return traceback.extract_stack()[-2][2] def I_want_to_kno

python 打印调用函数名和文件名

import inspect import sys def get_current_function_name(): funcName = sys._getframe().f_back.f_code.co_name # 获取调用函数名 print(dir(sys._getframe())) print(dir(sys._getframe().f_back.f_code.co_filename)) print(sys._getframe().f_back.f_code.co_filename,"#