Öze*_* B. 2 sql postgresql plpgsql
我正在尝试编写一个函数,该函数将 ID 作为输入并更新该给定 ID 上的一些字段。到目前为止,它看起来像这样:
CREATE FUNCTION update_status(p_id character varying,
p_status character varying DEFAULT NULL::character varying) RETURNS character varying
LANGUAGE plpgsql
AS
$$
DECLARE
v_row_count bigint DEFAULT 0;
v_result varchar(255);
BEGIN
IF p_id IS NOT NULL THEN
SELECT count(user_id)
INTO v_row_count
FROM test
WHERE user_id = p_id;
END IF;
IF v_row_count <= 0 THEN
v_result = 'User not found';
RETURN v_result;
ELSE
IF p_id NOT LIKE '%,%' THEN
UPDATE test
SET status = p_status,
updated_by = 'admin'
WHERE user_id IN (p_id);
ELSE
--Here comes split and pass multiple IDs into an IN() operator
END IF;
END IF;
END
$$;
ALTER FUNCTION update_status(varchar, varchar) OWNER TO postgres;
Run Code Online (Sandbox Code Playgroud)
现在,它应该一次只接受一个 ID,但我想知道是否可以通过将单个字符串拆分为一个 ID 数组(如果它有逗号分隔符)来一次接受多个 ID(甚至可能是数百个 ID),然后将它们传递给IN()
操作员。如何将字符串拆分为数组,以便将其提供给IN()
运算符?
小智 6
Blue Star 已经提到有一个内置函数可以将逗号分隔的字符串转换为数组。
但我建议不要首先传递逗号分隔的字符串。如果要传递可变数量的 ID,请使用variadic
参数。
您也不需要首先运行 SELECT,您可以询问系统在 UPDATE 语句之后更新了多少行。
CREATE FUNCTION update_status(p_status text, p_id variadic integer[])
RETURNS character varying
LANGUAGE plpgsql
AS
$$
DECLARE
v_row_count bigint DEFAULT 0;
BEGIN
UPDATE test
SET status = p_status,
updated_by = 'admin'
WHERE user_id = any (p_id);
get diagnostics v_row_count = row_count;
if v_row_count = 0 then
return 'User not found';
end if;
return concat(v_row_count, ' users updated');
END
$$;
Run Code Online (Sandbox Code Playgroud)
你可以这样使用它:
select update_status('active', 1);
select update_status('active', 5, 8, 42);
Run Code Online (Sandbox Code Playgroud)
如果由于某种原因,您“必须”将其作为单个参数传递,请改用真正的数组:
CREATE FUNCTION update_status(p_status text, p_id integer[])
Run Code Online (Sandbox Code Playgroud)
然后像这样传递:
select update_status('active', array[5,8,42]);
Run Code Online (Sandbox Code Playgroud)
或者
select update_status('active', '{5,8,42}');
Run Code Online (Sandbox Code Playgroud)