1

plpgsql语言的函数中,并具有:

  1. "col" CHARACTER VARYING = 'a';(可以'b'
  2. "rec" RECORD;持有记录来自:(SELECT 1 AS "a", 2 AS "b")
  3. "res" INTEGER;

"col"我需要从中引用命名列"rec"。所以如果"col"'b'我会引用"rec"."b",然后将其值保存到"res".

4

1 回答 1

2

您不能在 plpgsql 中按名称引用匿名记录类型的列。即使您在SELECT语句中的示例中拼出列别名,这些也只是噪音并被丢弃。

如果要按名称引用记录类型的元素,则需要使用众所周知的类型。创建并使用一个类型:

CREATE TYPE my_composite_type(a int, b int);

或者使用与任何现有表关联的行类型。您可以将表名写为数据类型。

DECLARE
   rec my_composite_type;
...

然后你需要一个条件语句动态 SQL来使用作为标识符的"col"

条件语句:

IF col = 'a' THEN
   res := rec.a;
ELSIF col = 'b' THEN
   res := rec.b;
ELSE
   RAISE EXCEPTION 'Unexpected value in variable "col": %', col;
END IF;

对于两种可能的情况,这就是要走的路。
或动态 SQL:

EXECUTE 'SELECT $1.' || col
INTO res
USING rec;

我在这里没有看到问题,但要小心使用动态 SQL 进行 SQL 注入。如果col可以保存任意数据,则需要使用quote_ident()or转义它format()

演示

使用动态 SQL 演示更强大但也更复杂的变体。

创建(临时!)已知类型进行测试的快速而肮脏的方法:

CREATE TEMP TABLE rec_ab(a int, b int);

功能:

CREATE OR REPLACE FUNCTION f_test()
  RETURNS integer AS
$func$
DECLARE
    col   text := 'a';  -- can be 'b'
    rec   rec_ab;
    res   int;
BEGIN
    rec := '(1, 2)'::rec_ab;

    EXECUTE 'SELECT $1.' || col
    INTO res
    USING rec;

    RETURN res;
END
$func$
  LANGUAGE plpgsql VOLATILE;

称呼:

SELECT f_test();

回报:

f_test
----
1
于 2013-01-03T22:59:57.023 回答