Postgresql 函数返回具有动态列名的行集
我有一个通用的键/值表,我想在一个函数中预处理它以按键过滤,然后根据键命名值 该表是这样的,Postgresql 函数返回具有动态列名的行集,postgresql,Postgresql,我有一个通用的键/值表,我想在一个函数中预处理它以按键过滤,然后根据键命名值 该表是这样的,id指向另一个表(但实际上是不关心这个问题): 等等。键值可能不同,并且并非所有ID都使用相同的键 具体来说,我想做的是创建一个函数,该函数将生成与给定键匹配的行。然后,它将为每个匹配的键返回一行,并使用该键命名值 因此,给定key name参数'x'的函数输出将与我执行以下命令时相同: SELECT id, value x FROM keyed_values WHERE key = 'x'; id |
id
指向另一个表(但实际上是不关心这个问题):
等等。键值可能不同,并且并非所有ID都使用相同的键
具体来说,我想做的是创建一个函数,该函数将生成与给定键匹配的行。然后,它将为每个匹配的键
返回一行,并使用该键命名值
因此,给定key name参数'x'
的函数输出将与我执行以下命令时相同:
SELECT id, value x FROM keyed_values WHERE key = 'x';
id | x
----+-------------------
1 | Value for x for 1
2 | Value for x for 2
(2 rows)
以下是我的观点,从其他一些SO答案中总结出来:
CREATE FUNCTION value_for(key TEXT) RETURNS SETOF RECORD AS $$
BEGIN
RETURN QUERY EXECUTE format('SELECT id, value %I FROM keyed_values WHERE key = %I', key, key);
END;
$$ LANGUAGE 'plpgsql';
该功能已被接受。但是当我执行它时,我得到了这个错误:
SELECT * FROM value_for('x');
ERROR: a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM value_for('x');
我明白它告诉我的,但不知道如何解决。如何动态定义输出列名?在
WHERE
子句中使用的键不是标识符,而是文本,因此函数应该如下所示:
CREATE FUNCTION value_for(key TEXT) RETURNS SETOF RECORD AS $$
BEGIN
RETURN QUERY EXECUTE format('SELECT id, value %I FROM keyed_values WHERE key = %L', key, key);
END;
$$ LANGUAGE plpgsql;
从
如果已将函数定义为返回记录数据类型,则必须存在别名或关键字as,后跟格式为的列定义列表(列名称数据类型[,…])。列定义列表必须与函数返回的实际列数和类型匹配
使用列定义列表:
SELECT * FROM value_for('x') AS (id int, x text);
请注意,您不需要动态SQL或plpgsql,因为列名称在上面的列表中定义。简单SQL函数应该快一点:
CREATE OR REPLACE FUNCTION value_for(_key text)
RETURNS SETOF RECORD AS $$
SELECT id, value
FROM keyed_values
WHERE key = _key
$$ LANGUAGE SQL;
如果您不喜欢被强制为每个函数调用追加列定义列表,则可以从函数返回一个表:
CREATE OR REPLACE FUNCTION value_for_2(_key text)
RETURNS TABLE(id int, x text) AS $$
SELECT id, value
FROM keyed_values
WHERE key = _key
$$ LANGUAGE SQL;
SELECT * FROM value_for_2('x');
id | x
----+-------------------
1 | Value for x for 1
2 | Value for x for 2
(2 rows)
然而,这并不能解决问题。无法动态定义从函数返回的列名。在执行查询之前,必须指定返回列的名称和类型。您不能这样做。列名来自函数定义,或者在调用时必须命名列。
CREATE OR REPLACE FUNCTION value_for_2(_key text)
RETURNS TABLE(id int, x text) AS $$
SELECT id, value
FROM keyed_values
WHERE key = _key
$$ LANGUAGE SQL;
SELECT * FROM value_for_2('x');
id | x
----+-------------------
1 | Value for x for 1
2 | Value for x for 2
(2 rows)