PostgreSQL 11 - 使用格式分配给变量
PostgreSQL 11 - using format to assign to variable
我已经醒了很久,超出了我的日程安排,我已经被这个问题困扰了很长时间,我什至不知道我要解决什么,但我想使用格式来插入值我将用于列名,然后执行它...但无论我尝试更改多少,它都会给我错误:c
这是我试图做一些不起作用的部分,但我想你明白我想要实现的目标
ratelimit := EXECUTE format('(SELECT %I
FROM users.ratelimits
WHERE user_id = )
', );
下面是勇敢者的完整代码
CREATE OR REPLACE FUNCTION users.consume_ratelimit(_name text,__user_id integer)
RETURNS boolean
LANGUAGE 'plpgsql'
VOLATILE
PARALLEL UNSAFE
COST 100
AS $BODY$DECLARE
ratelimit INTEGER;
reset_timeout timestamptz;
premium BOOLEAN;
BEGIN
ratelimit := EXECUTE format('(SELECT %I
FROM users.ratelimits
WHERE user_id = )
', );
reset_timeout := EXECUTE format('(SELECT %I_refresh
FROM users.ratelimits
WHERE user_id = )
', );
premium := (SELECT users.is_premium());
IF premium THEN
RETURN TRUE;
ELSIF reset_timeout <= NOW() THEN
UPDATE users.ratelimits
SET image_refresh = NOW() + '1 hour'::interval,
image = DEFAULT
WHERE user_id = ;
RAISE NOTICE 'reset';
RETURN TRUE;
ELSE
IF ratelimit > 0 THEN
EXECUTE format('UPDATE users.ratelimits
SET %I = %I - 1
WHERE user_id = ', , );
RAISE NOTICE 'decrement';
RETURN TRUE;
ELSIF ratelimit <= 0 THEN
RAISE NOTICE 'out of credits';
RETURN FALSE;
ELSE
EXECUTE format('INSERT INTO users.ratelimits(user_id) VALUES ()
ON CONFLICT DO UPDATE SET
%I = excluded.%I,
%I_refresh = excluded.%I_refresh', , , , );
RAISE NOTICE 'create';
RETURN TRUE;
END IF;
END IF;
END;$BODY$;
看来some_var := EXECUTE ...
不行。此外,EXECUTE 语句中的参数与函数中的参数不同——您需要将它们提供给 execute 语句。
我没有测试过这个,但也许
-- q declared above as text
q := format('
SELECT %I
FROM users.ratelimits
WHERE user_id = %s;
', , );
EXECUTE q INTO ratelimit;
有用吗?我还从查询中删除了括号,这些是不必要的,可能本身就是问题。
我已经测试了功能
CREATE OR REPLACE FUNCTION test_sum (a int, b int)
RETURNS int
AS $$
DECLARE
q text;
result int;
BEGIN
q := FORMAT ('SELECT %s + %s', , );
EXECUTE q INTO result;
RETURN result;
END
$$ LANGUAGE plpgsql
这确实有效。如果我上面的建议不起作用,也许你可以从上面的开始。
As documented in the manual 您需要使用 into
和 EXECUTE 一起将结果存储到变量中。这也可以处理多个 columns/variables,因此您只需要一个 EXECUTE 即可获取两个值。
为清楚起见,您应该按名称而非位置引用参数。
EXECUTE format('SELECT %I, %I_refresh
FROM users.ratelimits WHERE user_id = '),
_name, _name)
USING __user_id
INTO ratelimit, reset_timeout;
注意format()
字符串中的</code>是执行SQL语句时使用的参数占位符,将被替换为SQL语句中指定的变量值<code>USING
子句。
没有 SELECT 的变量赋值也更有效:
premium := users.is_premium(__user_id);
我已经醒了很久,超出了我的日程安排,我已经被这个问题困扰了很长时间,我什至不知道我要解决什么,但我想使用格式来插入值我将用于列名,然后执行它...但无论我尝试更改多少,它都会给我错误:c
这是我试图做一些不起作用的部分,但我想你明白我想要实现的目标
ratelimit := EXECUTE format('(SELECT %I
FROM users.ratelimits
WHERE user_id = )
', );
下面是勇敢者的完整代码
CREATE OR REPLACE FUNCTION users.consume_ratelimit(_name text,__user_id integer)
RETURNS boolean
LANGUAGE 'plpgsql'
VOLATILE
PARALLEL UNSAFE
COST 100
AS $BODY$DECLARE
ratelimit INTEGER;
reset_timeout timestamptz;
premium BOOLEAN;
BEGIN
ratelimit := EXECUTE format('(SELECT %I
FROM users.ratelimits
WHERE user_id = )
', );
reset_timeout := EXECUTE format('(SELECT %I_refresh
FROM users.ratelimits
WHERE user_id = )
', );
premium := (SELECT users.is_premium());
IF premium THEN
RETURN TRUE;
ELSIF reset_timeout <= NOW() THEN
UPDATE users.ratelimits
SET image_refresh = NOW() + '1 hour'::interval,
image = DEFAULT
WHERE user_id = ;
RAISE NOTICE 'reset';
RETURN TRUE;
ELSE
IF ratelimit > 0 THEN
EXECUTE format('UPDATE users.ratelimits
SET %I = %I - 1
WHERE user_id = ', , );
RAISE NOTICE 'decrement';
RETURN TRUE;
ELSIF ratelimit <= 0 THEN
RAISE NOTICE 'out of credits';
RETURN FALSE;
ELSE
EXECUTE format('INSERT INTO users.ratelimits(user_id) VALUES ()
ON CONFLICT DO UPDATE SET
%I = excluded.%I,
%I_refresh = excluded.%I_refresh', , , , );
RAISE NOTICE 'create';
RETURN TRUE;
END IF;
END IF;
END;$BODY$;
看来some_var := EXECUTE ...
不行。此外,EXECUTE 语句中的参数与函数中的参数不同——您需要将它们提供给 execute 语句。
我没有测试过这个,但也许
-- q declared above as text
q := format('
SELECT %I
FROM users.ratelimits
WHERE user_id = %s;
', , );
EXECUTE q INTO ratelimit;
有用吗?我还从查询中删除了括号,这些是不必要的,可能本身就是问题。
我已经测试了功能
CREATE OR REPLACE FUNCTION test_sum (a int, b int)
RETURNS int
AS $$
DECLARE
q text;
result int;
BEGIN
q := FORMAT ('SELECT %s + %s', , );
EXECUTE q INTO result;
RETURN result;
END
$$ LANGUAGE plpgsql
这确实有效。如果我上面的建议不起作用,也许你可以从上面的开始。
As documented in the manual 您需要使用 into
和 EXECUTE 一起将结果存储到变量中。这也可以处理多个 columns/variables,因此您只需要一个 EXECUTE 即可获取两个值。
为清楚起见,您应该按名称而非位置引用参数。
EXECUTE format('SELECT %I, %I_refresh
FROM users.ratelimits WHERE user_id = '),
_name, _name)
USING __user_id
INTO ratelimit, reset_timeout;
注意format()
字符串中的</code>是执行SQL语句时使用的参数占位符,将被替换为SQL语句中指定的变量值<code>USING
子句。
没有 SELECT 的变量赋值也更有效:
premium := users.is_premium(__user_id);