【问题标题】:Unable to call a PostgreSQL function using callable statement or prepared statement无法使用可调用语句或预准备语句调用 PostgreSQL 函数
【发布时间】:2020-07-20 14:29:34
【问题描述】:

我创建了一个 PostgreSQL 函数,该函数在后端进行了测试,它按预期工作。但是,当我尝试通过 Scala 模块调用它时,它说该函数不存在。

Function:

create or replace function testing.compareData(ab integer, b json, tablename varchar) RETURNS void as $$
  DECLARE 
  actualTableName varchar := tablename;
  histTableName varchar:= actualTableName ||'_hist';
  job_id Integer:=0;
begin --<<<< HERE
  set search_path to testing; -- Set the schema name
  execute 'SELECT id FROM '||actualTableName||' WHERE id =$1' into job_id using ab;
  -- if there is data for id in the table then perform below operations
  if job_id is not null then
      execute FORMAT('INSERT INTO %I select * from %I where id = $1',histTableName,actualTableName) USING ab;
      execute FORMAT('DELETE FROM %I where id = $1',actualTableName) USING ab;
      EXECUTE FORMAT('INSERT INTO %I values($1,$2)',actualTableName) USING ab,b;
  -- if id is not present then create a new record in the actualTable
  ELSE    
      EXECUTE FORMAT('INSERT INTO %I values($1,$2)',actualTableName) USING ab,b;
  END IF;

END; --<<<< END HERE
$$ LANGUAGE plpgsql;

Callable Statement方式:

def callingStoredProcedure(message: String, id: Integer, resourceType: String): Unit = {
    val connectionUrl: String = ReadingConfig.postgreDBDetails().get("url").getOrElse("None")
    var conn: Connection = null
    var callableStatement: CallableStatement = null
    try {
      conn = DriverManager.getConnection(connectionUrl)
      callableStatement = conn.prepareCall("{ call testing.compareData( ?,?,? ) }")
      callableStatement.setString(1, message)
      callableStatement.setInt(2, id)
      callableStatement.setString(3, resourceType)
      callableStatement.execute()
    } catch {
      case up: Exception =>
        throw up
    } finally {
      conn.close()
    }
  }  

Prepared Statement方式:

def callDataCompareAndInsertFunction(message: String, id: Integer, resourceType: String): Unit = {
    val connectionUrl: String = ReadingConfig.postgreDBDetails().get("url").getOrElse("None")
    var pstmt: PreparedStatement = null
    var conn: Connection = null
    try {
      conn = DriverManager.getConnection(connectionUrl)
      pstmt = conn.prepareStatement("select testing.compareData(?,?,?)")
      pstmt.setInt(1, id)
      pstmt.setString(2, message)
      pstmt.setString(3, resourceType)
      pstmt.executeQuery()
    }
    catch {
      case e: Exception => throw e
    }
    finally {
      conn.close()
    }
  }  

这里,testing 是我创建函数的架构。当使用这两种方式运行时,它会抛出以下错误:

Exception in thread "main" org.postgresql.util.PSQLException: ERROR: function testing.comparedata(character varying, integer, character varying) does not exist
  Hint: No function matches the given name and argument types. You might need to add explicit type casts.

【问题讨论】:

  • edit您的问题并添加您用于创建函数的确切create function语句
  • 新增功能。请看一眼
  • 会推荐使用一些 Scala DB 库
  • 你能推荐一些吗?

标签: postgresql scala function stored-procedures


【解决方案1】:

您的第一个参数不是字符串,因此调用setString(1, ...) 将导致您在问题中引用的错误。

您的第二个参数被声明为json,因此您也不能直接在那里传递字符串值。以下应该可以工作(给定函数定义):

  pstmt = conn.prepareStatement("select testing.compareData(?,cast(? as json),?)")
  pstmt.setInt(1, id)
  pstmt.setString(2, message)
  pstmt.setString(3, resourceType)

您可能还需要使用pstmt.execute() 而不是executeQuery(),因为您的函数不会返回任何内容。

【讨论】:

  • 是的,谢谢你的回答。有效。我必须做的一个小改动就是将jsonb 更改为json,因为不知何故它不起作用,而且我在你的答案中进行了编辑。你让我开心:)
  • 啊,对。我没看到你使用的是json 而不是jsonb(你应该使用)
  • 是的,但我不想采用二进制形式,因为稍后其他模块可能会对该 JSON 执行操作。
  • 您不必以“二进制形式”处理它,这只是 Postgres 存储值的不同方式。 quote from the manual "一般来说,大多数应用程序应该更喜欢将 JSON 数据存储为 jsonb,除非有非常特殊的需求,例如关于对象键排序的遗留假设"
  • 哦,好的。我也会试试的。感谢您指出。以及我对可调用语句的方式有点好奇。为什么那部分不起作用?是因为那个选角吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多