如何将数组或列表传递给 PostgreSQL 中的存储过程
How to pass an array or list to a stored procedure in PostgreSQL
我正在尝试在 PostgreSQL 中开发一个存储的 procedure/function 来接受和处理来自 SSRS 的列表。我在将列表传递给存储过程时遇到了一些问题。这是查询
CREATE OR REPLACE FUNCTION get_transaction_all_accounts(p_property[] varchar, p_year timestamp without time zone)
RETURNS record
LANGUAGE plpgsql
AS $function$
DECLARE
l_num_property numeric(15,2);
l_num_amount numeric(15,2);
l_property varchar := '';
l_year timestamp := LOCALTIMESTAMP;
result RECORD;
BEGIN
IF ( p_property IS NOT NULL ) THEN
l_property := p_property;
END IF;
IF ( p_year IS NOT NULL ) THEN
l_year := p_year;
END IF;
SELECT INTO l_num_property, l_num_amount
property::numeric(15,2), coalesce(sum(amount),0)::numeric(15,2) from (
select a.propertyname AS property, a.amount
FROM sw."fTransaction" a
WHERE a.propertyname = l_property
)as foo;
SELECT INTO result l_num_property, l_num_amount;
RETURN result;
END;
$function$
;
-- Permissions
ALTER FUNCTION get_transaction_all_accounts(varchar,timestamp) OWNER TO myuser;
GRANT ALL ON FUNCTION get_transaction_all_accounts(varchar,timestamp) TO myuser;
这里是数据集查询
select sum(amount) as sink from get_transaction_all_accounts(?,?, -1) as ("property" numeric, "amount" numeric)
我使用的参数表达式:
Join(Parameters!property.Value,",")
DateAdd("d", 1, Parameters!date.Value)
我不知道如何处理将列表数据传递给函数参数的查询。请帮我做这个
谢谢
使用逗号分隔的输入值和其他值的函数,并准备动态查询,其中输入参数很少(如果提供),并使用 regexp_split_to_table 将逗号分隔的值拆分为列表。如果 null 或空字符串 ('') 用作输入值,则相关列名称不用于搜索条件。
-- PostgreSQL (v14)
-- Function: public.rpt_member_info(character varying, character varying, character varying, character varying, character varying)
DROP FUNCTION IF EXISTS public.rpt_member_info(character varying, character varying, character varying, character varying, character varying);
CREATE OR REPLACE FUNCTION public.rpt_member_info(
IN p_officeInfoId CHARACTER VARYING,
IN p_projectInfoId CHARACTER VARYING,
IN p_memberInfoId CHARACTER VARYING,
IN p_fromDate CHARACTER VARYING,
IN p_toDate CHARACTER VARYING,
OUT member_id BIGINT,
out office_info_id bigint,
out project_info_id bigint,
OUT member_no CHARACTER VARYING,
OUT member_name CHARACTER VARYING,
OUT membership_date TIMESTAMP WITHOUT TIME ZONE)
RETURNS SETOF record AS
$BODY$
-- declare local variables
DECLARE v_prepareQuery VARCHAR(21840) DEFAULT '';
v_officeInfo VARCHAR(150) DEFAULT '';
v_projectInfo VARCHAR(150) DEFAULT '';
v_memberInfo VARCHAR(150) DEFAULT '';
refcur refcursor default 'test';
BEGIN
/**************************History**************************/
-- Name : rpt_member_info
-- Created Date (dd/MM/yyyy): 01/02/2022
-- Created By : Rahul Biswas
-- Reason :
-- Execute : SELECT * FROM rpt_member_info('101', '1', '1', '2022-01-01', '2022-01-31');
/***********************************************************/
-- prepare variable data based on given input
IF(p_officeInfoId != '' AND p_officeInfoId != 'null' AND p_officeInfoId IS NOT NULL)
THEN
v_officeInfo = CONCAT(' AND mi.office_info_id = ANY(SELECT CAST(regexp_split_to_table(''', p_officeInfoId, ''',''', ', '') AS BIGINT))', CHR(10));
END IF;
IF(p_projectInfoId != '' AND p_projectInfoId != 'null' AND p_projectInfoId IS NOT NULL)
THEN
v_projectInfo = CONCAT(' AND mi.project_info_id = ', p_projectInfoId, CHR(10));
END IF;
IF(p_memberInfoId != '' AND p_memberInfoId != 'null' AND p_memberInfoId IS NOT NULL)
THEN
v_memberInfo = CONCAT(' AND mi.id = ', p_memberInfoId, CHR(10));
END IF;
-- prepare query
v_prepareQuery := CONCAT('SELECT mi.id member_id
, mi.office_info_id
, mi.project_info_id
, mi.member_no
, mi.member_name
, mi.membership_date
FROM member_info mi
WHERE 1 = 1', CHR(10)
, v_officeInfo
, v_projectInfo
, v_memberInfo
, 'AND mi.membership_date BETWEEN ', '''', p_fromDate, '''', ' AND ', '''', p_toDate, '''', ';');
RETURN QUERY EXECUTE v_prepareQuery;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
执行这个函数
SELECT * FROM rpt_member_info('101, 102', '1', '', '2022-01-01', '2022-01-31');
请检查这个urlhttps://dbfiddle.uk/?rdbms=postgres_14&fiddle=a38347cb181d0347a06ba6304e9448ef
如果不使用动态查询并提供逗号分隔值作为输入,则使用以下函数
-- Function: public.rpt_member_info(character varying, bigint, TIMESTAMP WITHOUT TIME ZONE, bigint, TIMESTAMP WITHOUT TIME ZONE, TIMESTAMP WITHOUT TIME ZONE)
DROP FUNCTION IF EXISTS public.rpt_member_info(character varying, bigint, TIMESTAMP WITHOUT TIME ZONE, TIMESTAMP WITHOUT TIME ZONE);
CREATE OR REPLACE FUNCTION public.rpt_member_info(
IN p_officeInfoId CHARACTER VARYING,
IN p_projectInfoId BIGINT,
IN p_fromDate TIMESTAMP WITHOUT TIME ZONE,
IN p_toDate TIMESTAMP WITHOUT TIME ZONE,
OUT member_id BIGINT,
out office_info_id bigint,
out project_info_id bigint,
OUT member_no CHARACTER VARYING,
OUT member_name CHARACTER VARYING,
OUT membership_date TIMESTAMP WITHOUT TIME ZONE)
RETURNS SETOF record AS
$BODY$
-- declare local variables
DECLARE v_prepareQuery VARCHAR(21840) DEFAULT '';
v_officeInfo VARCHAR(150) DEFAULT '';
v_projectInfo VARCHAR(150) DEFAULT '';
v_memberInfo VARCHAR(150) DEFAULT '';
refcur refcursor default 'test';
BEGIN
/**************************History**************************/
-- Name : rpt_member_info
-- Created Date (dd/MM/yyyy): 01/02/2022
-- Created By : Rahul Biswas
-- Reason :
-- Execute : SELECT * FROM rpt_member_info('101, 102', 1, '2022-01-01', '2022-01-31');
/***********************************************************/
-- execute query
RETURN QUERY SELECT mi.id member_id
, mi.office_info_id
, mi.project_info_id
, mi.member_no
, mi.member_name
, mi.membership_date
FROM member_info mi
WHERE mi.office_info_id = ANY(SELECT CAST(regexp_split_to_table(p_officeInfoId, ',') AS BIGINT))
AND mi.project_info_id = p_projectInfoId
AND mi.membership_date BETWEEN p_fromDate AND p_toDate;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
执行函数
SELECT * FROM rpt_member_info('101, 102', 1, '2022-01-01', '2022-01-31');
请用这个urlhttps://dbfiddle.uk/?rdbms=postgres_14&fiddle=ee5b70bbb8fbeacbb9fad280cc775b58
N.B.: 在较低版本的 Postgresql 中,函数和存储过程的行为相同。
我正在尝试在 PostgreSQL 中开发一个存储的 procedure/function 来接受和处理来自 SSRS 的列表。我在将列表传递给存储过程时遇到了一些问题。这是查询
CREATE OR REPLACE FUNCTION get_transaction_all_accounts(p_property[] varchar, p_year timestamp without time zone)
RETURNS record
LANGUAGE plpgsql
AS $function$
DECLARE
l_num_property numeric(15,2);
l_num_amount numeric(15,2);
l_property varchar := '';
l_year timestamp := LOCALTIMESTAMP;
result RECORD;
BEGIN
IF ( p_property IS NOT NULL ) THEN
l_property := p_property;
END IF;
IF ( p_year IS NOT NULL ) THEN
l_year := p_year;
END IF;
SELECT INTO l_num_property, l_num_amount
property::numeric(15,2), coalesce(sum(amount),0)::numeric(15,2) from (
select a.propertyname AS property, a.amount
FROM sw."fTransaction" a
WHERE a.propertyname = l_property
)as foo;
SELECT INTO result l_num_property, l_num_amount;
RETURN result;
END;
$function$
;
-- Permissions
ALTER FUNCTION get_transaction_all_accounts(varchar,timestamp) OWNER TO myuser;
GRANT ALL ON FUNCTION get_transaction_all_accounts(varchar,timestamp) TO myuser;
这里是数据集查询
select sum(amount) as sink from get_transaction_all_accounts(?,?, -1) as ("property" numeric, "amount" numeric)
我使用的参数表达式:
Join(Parameters!property.Value,",")
DateAdd("d", 1, Parameters!date.Value)
我不知道如何处理将列表数据传递给函数参数的查询。请帮我做这个
谢谢
使用逗号分隔的输入值和其他值的函数,并准备动态查询,其中输入参数很少(如果提供),并使用 regexp_split_to_table 将逗号分隔的值拆分为列表。如果 null 或空字符串 ('') 用作输入值,则相关列名称不用于搜索条件。
-- PostgreSQL (v14)
-- Function: public.rpt_member_info(character varying, character varying, character varying, character varying, character varying)
DROP FUNCTION IF EXISTS public.rpt_member_info(character varying, character varying, character varying, character varying, character varying);
CREATE OR REPLACE FUNCTION public.rpt_member_info(
IN p_officeInfoId CHARACTER VARYING,
IN p_projectInfoId CHARACTER VARYING,
IN p_memberInfoId CHARACTER VARYING,
IN p_fromDate CHARACTER VARYING,
IN p_toDate CHARACTER VARYING,
OUT member_id BIGINT,
out office_info_id bigint,
out project_info_id bigint,
OUT member_no CHARACTER VARYING,
OUT member_name CHARACTER VARYING,
OUT membership_date TIMESTAMP WITHOUT TIME ZONE)
RETURNS SETOF record AS
$BODY$
-- declare local variables
DECLARE v_prepareQuery VARCHAR(21840) DEFAULT '';
v_officeInfo VARCHAR(150) DEFAULT '';
v_projectInfo VARCHAR(150) DEFAULT '';
v_memberInfo VARCHAR(150) DEFAULT '';
refcur refcursor default 'test';
BEGIN
/**************************History**************************/
-- Name : rpt_member_info
-- Created Date (dd/MM/yyyy): 01/02/2022
-- Created By : Rahul Biswas
-- Reason :
-- Execute : SELECT * FROM rpt_member_info('101', '1', '1', '2022-01-01', '2022-01-31');
/***********************************************************/
-- prepare variable data based on given input
IF(p_officeInfoId != '' AND p_officeInfoId != 'null' AND p_officeInfoId IS NOT NULL)
THEN
v_officeInfo = CONCAT(' AND mi.office_info_id = ANY(SELECT CAST(regexp_split_to_table(''', p_officeInfoId, ''',''', ', '') AS BIGINT))', CHR(10));
END IF;
IF(p_projectInfoId != '' AND p_projectInfoId != 'null' AND p_projectInfoId IS NOT NULL)
THEN
v_projectInfo = CONCAT(' AND mi.project_info_id = ', p_projectInfoId, CHR(10));
END IF;
IF(p_memberInfoId != '' AND p_memberInfoId != 'null' AND p_memberInfoId IS NOT NULL)
THEN
v_memberInfo = CONCAT(' AND mi.id = ', p_memberInfoId, CHR(10));
END IF;
-- prepare query
v_prepareQuery := CONCAT('SELECT mi.id member_id
, mi.office_info_id
, mi.project_info_id
, mi.member_no
, mi.member_name
, mi.membership_date
FROM member_info mi
WHERE 1 = 1', CHR(10)
, v_officeInfo
, v_projectInfo
, v_memberInfo
, 'AND mi.membership_date BETWEEN ', '''', p_fromDate, '''', ' AND ', '''', p_toDate, '''', ';');
RETURN QUERY EXECUTE v_prepareQuery;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
执行这个函数
SELECT * FROM rpt_member_info('101, 102', '1', '', '2022-01-01', '2022-01-31');
请检查这个urlhttps://dbfiddle.uk/?rdbms=postgres_14&fiddle=a38347cb181d0347a06ba6304e9448ef
如果不使用动态查询并提供逗号分隔值作为输入,则使用以下函数
-- Function: public.rpt_member_info(character varying, bigint, TIMESTAMP WITHOUT TIME ZONE, bigint, TIMESTAMP WITHOUT TIME ZONE, TIMESTAMP WITHOUT TIME ZONE)
DROP FUNCTION IF EXISTS public.rpt_member_info(character varying, bigint, TIMESTAMP WITHOUT TIME ZONE, TIMESTAMP WITHOUT TIME ZONE);
CREATE OR REPLACE FUNCTION public.rpt_member_info(
IN p_officeInfoId CHARACTER VARYING,
IN p_projectInfoId BIGINT,
IN p_fromDate TIMESTAMP WITHOUT TIME ZONE,
IN p_toDate TIMESTAMP WITHOUT TIME ZONE,
OUT member_id BIGINT,
out office_info_id bigint,
out project_info_id bigint,
OUT member_no CHARACTER VARYING,
OUT member_name CHARACTER VARYING,
OUT membership_date TIMESTAMP WITHOUT TIME ZONE)
RETURNS SETOF record AS
$BODY$
-- declare local variables
DECLARE v_prepareQuery VARCHAR(21840) DEFAULT '';
v_officeInfo VARCHAR(150) DEFAULT '';
v_projectInfo VARCHAR(150) DEFAULT '';
v_memberInfo VARCHAR(150) DEFAULT '';
refcur refcursor default 'test';
BEGIN
/**************************History**************************/
-- Name : rpt_member_info
-- Created Date (dd/MM/yyyy): 01/02/2022
-- Created By : Rahul Biswas
-- Reason :
-- Execute : SELECT * FROM rpt_member_info('101, 102', 1, '2022-01-01', '2022-01-31');
/***********************************************************/
-- execute query
RETURN QUERY SELECT mi.id member_id
, mi.office_info_id
, mi.project_info_id
, mi.member_no
, mi.member_name
, mi.membership_date
FROM member_info mi
WHERE mi.office_info_id = ANY(SELECT CAST(regexp_split_to_table(p_officeInfoId, ',') AS BIGINT))
AND mi.project_info_id = p_projectInfoId
AND mi.membership_date BETWEEN p_fromDate AND p_toDate;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
执行函数
SELECT * FROM rpt_member_info('101, 102', 1, '2022-01-01', '2022-01-31');
请用这个urlhttps://dbfiddle.uk/?rdbms=postgres_14&fiddle=ee5b70bbb8fbeacbb9fad280cc775b58
N.B.: 在较低版本的 Postgresql 中,函数和存储过程的行为相同。