gpt4 book ai didi

java - 如何在 pl/pgsql 中创建返回 refcursor 和totalRow 的函数/过程?

转载 作者:行者123 更新时间:2023-11-30 06:05:06 27 4
gpt4 key购买 nike

pl/pgsql中,我想创建函数/过程来返回表和totalRecord的结果列表(返回记录),所以我创建了这个函数:

CREATE OR REPLACE FUNCTION GET_LIST_NOTIFY(    
-- Cursor param
out PO_Cursor refcursor, -- return Resutlset
out PO_ErrorCode VARCHAR,
out PO_ErrorDesc VARCHAR,
OUT PO_TotalRow VARCHAR
)
as
$$
declare
-- Variable Declare
vSqlSel VARCHAR(20000); -- Sql select
-- END Variable Declare
begin
PO_ErrorCode := 'CODE';
PO_ErrorDesc := 'MSG_DESC';

vSqlSel := 'SELECT ID, TITLE ' ||
' FROM USER_NOTIFICATION ';

raise info 'sql select : %', vSqlSel;

-- open cursor
OPEN PO_Cursor for execute vSqlSel;
EXECUTE 'SELECT count(*) FROM USER_NOTIFICATION' INTO PO_TotalRow;
EXCEPTION
WHEN OTHERS THEN
PO_ErrorCode := 'COMMONERROR_CODE';
PO_ErrorDesc := substr(SQLERRM,1,200);

RAISE;

END;
$$ LANGUAGE plpgsql;
-- END GET_LIST_NOTIFY

但是当我调用这个函数时,返回的结果是:

- refcursor is "<unnamed portal 1>"
- PO_ErrorCode is "CODE"
- PO_ErrorDesc is "MSG_DESC"
- PO_TotalRow is "10"

因此,我无法使用 refcursor 来检索并显示 java 中的记录数据。我该如何解决这个问题?

在oracle pl/sql中我可以这样写:

PROCEDURE GET_LIST_NOTIFY(
-- Fields param
PI_USERNAME IN VARCHAR2,
-- END Fields param

-- Cursor param
PO_Cursor OUT REF CURSOR,
PO_TotalRow OUT VARCHAR2,
PO_ErrorCode OUT VARCHAR2,
PO_ErrorDesc OUT VARCHAR2
)
AS
-- Variable Declare
vSqlSel VARCHAR2(20000); -- Sql select
-- END Variable Declare

BEGIN

PO_ErrorCode := 'SUCCESS_CODE';
PO_ErrorDesc := 'SUCCESS_MSG';

vSqlSel := 'SELECT ID, TITLE ' ||
' FROM USER_NOTIFICATION ';

dbms_output.put_line('sql select :' || vSqlSel);
EXECUTE IMMEDIATE 'SELECT count(*) FROM USER_NOTIFICATION' INTO PO_TotalRow;
-- open cursor
OPEN PO_Cursor FOR
vSqlSel;


EXCEPTION
WHEN OTHERS THEN
IF PO_Cursor%ISOPEN THEN
CLOSE PO_Cursor;
END IF;

PO_ErrorCode := 'COMMONERROR_CODE';
PO_ErrorDesc := substr(DBMS_UTILITY.format_error_backtrace || ' ' ||
SQLERRM,1,200);

RAISE;

END;
-- END GET_LIST_NOTIFY

在我的java代码中,我这样调用“get_list_notify”函数:

            RowMapper rowMapper = new RowMapper() {
@Override
public Object mapRow(ResultSet rs, int rownum) throws SQLException {
// TODO Auto-generated method stub
OptionDTO dto = new OptionDTO();
try {

dto.setValue(Utils.validateHTMLParam(rs.getString(1).trim(), false));
dto.setText(Utils.validateHTMLParam(rs.getString(2).trim(), false));

} catch (Exception e) {
ErrorHelper.PrintStackTrace(this.getClass().getName(), e, "DataProcessing.getDrowdownData2.OptionMapper.mapRow error : ");
}

return dto;
}
};

SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(DBConnector.getConnection())
.withFunctionName(procedureName).withoutProcedureColumnMetaDataAccess();
Map<String, Object> params = new LinkedHashMap();
for (String key : parameters.keySet()) {
simpleJdbcCall.addDeclaredParameter(new SqlParameter(key, parameters.get(key).getType()));
if(Utils.isNummericOracleType(parameters.get(key).getType()) && parameters.get(key).getData() != null)
params.put(key, new BigDecimal(parameters.get(key).getData().toString()));
else
params.put(key, parameters.get(key).getData());
}

simpleJdbcCall.addDeclaredParameter(new SqlOutParameter("PO_Cursor", Oid.REF_CURSOR, rowMapper));
simpleJdbcCall.addDeclaredParameter(new SqlOutParameter("PO_ErrorCode", Oid.VARCHAR));
simpleJdbcCall.addDeclaredParameter(new SqlOutParameter("PO_ErrorDesc", Oid.VARCHAR));

Map<String, Object> map = simpleJdbcCall.execute(params);

但是在执行时,simpleJdbcCall.execute(params)引发异常,如下所示:

[err] -----org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{? = call get_list_notify(?, ?, ?)}]; SQL state [34000]; error code [0]; ERROR: cursor "<unnamed portal 1>" does not exist; nested exception is org.postgresql.util.PSQLException: ERROR: cursor "<unnamed portal 1>" does not exist
[err] --------------- At classes : ---------------
[err] ----- at com.bidv.bidvwas.common.DataProccessing.getDrowdownData(DataProccessing.java:399)

如何准确转换 pl/pgsql 并解析来自 java 的调用函数。我使用 springjdbc-4.2.5 和 postgres 10.4

最佳答案

你的代码有点奇怪(太奇怪了 - 几乎有我知道的所有反模式:) - 在一个例子中)。您尝试连接应该分开的事物,并且尝试错误地使用存储过程。通常,过程不应提供 View (并非在所有没有 MSSQL 的数据库中)。通过过程,您的代码应该更具可读性,而不是更少。

您错过了命令FETCH 。您应该将其用于 <unnamed portal> .

CREATE OR REPLACE FUNCTION public.fx(par text, INOUT r refcursor, OUT result integer)
RETURNS record
LANGUAGE plpgsql
AS $function$
BEGIN
result := 10;
OPEN r FOR SELECT * FROM pg_class WHERE relname LIKE par;
END;
$function$
postgres=# SELECT fx('pg_c%', 'my_name_for_cursor');┌─────────────────────────┐│           fx            │╞═════════════════════════╡│ (my_name_for_cursor,10) │└─────────────────────────┘(1 row)postgres=# FETCH 10 FROM my_name_for_cursor;┌───────────────────────────────────┬──────────────┬─────────┬───────────┬──────────┬───────┬─────────────┬─────────────│              relname              │ relnamespace │ reltype │ reloftype │ relowner │ relam │ relfilenode │ reltablespac╞═══════════════════════════════════╪══════════════╪═════════╪═══════════╪══════════╪═══════╪═════════════╪═════════════│ pg_cast_oid_index                 │           11 │       0 │         0 │       10 │   403 │        2660 │             │ pg_cast_source_target_index       │           11 │       0 │         0 │       10 │   403 │        2661 │             │ pg_class_oid_index                │           11 │       0 │         0 │       10 │   403 │           0 │             │ pg_class_relname_nsp_index        │           11 │       0 │         0 │       10 │   403 │           0 │             │ pg_class_tblspc_relfilenode_index │           11 │       0 │         0 │       10 │   403 │           0 │             │ pg_collation_name_enc_nsp_index   │           11 │       0 │         0 │       10 │   403 │        3164 │             │ pg_collation_oid_index            │           11 │       0 │         0 │       10 │   403 │        3085 │             │ pg_constraint_conname_nsp_index   │           11 │       0 │         0 │       10 │   403 │        2664 │             │ pg_constraint_conrelid_index      │           11 │       0 │         0 │       10 │   403 │        2665 │             │ pg_constraint_contypid_index      │           11 │       0 │         0 │       10 │   403 │        2666 │             └───────────────────────────────────┴──────────────┴─────────┴───────────┴──────────┴───────┴─────────────┴─────────────(10 rows)postgres=# COMMIT;

更多 - 您使用动态 SQL 太多(命令 EXECUTE )。较新的版本在不需要时使用动态 SQL。在您的示例中,永远不应该使用动态 SQL。

捕获所有错误通常也是个坏主意。这是客户端的工作,而不是存储过程中的代码。仅处理您可以正确解决的错误。有关异常的所有信息也可以在客户端获取,并且您不需要编写这些晦涩的包装器。

关于java - 如何在 pl/pgsql 中创建返回 refcursor 和totalRow 的函数/过程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51508823/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com