Postgresql 从保存列名的变量引用记录的列

Postgresql 从保存列名的变量引用记录的列,postgresql,plpgsql,dynamic-sql,Postgresql,Plpgsql,Dynamic Sql,在plpgsql语言的函数中,具有: “col”字符变化='a'(可以是'b') “rec”记录从以下位置保存记录:(选择1作为“a”,选择2作为“b”) “res”整数 我需要引用“col”中来自“rec”的命名列。因此,如果“col”具有“b”,我将引用“rec.”“b”,然后将其值保存到“res”中,您不能在plpgsql中按名称引用匿名记录类型的列。即使您在示例中的SELECT语句中拼出了列别名,但它们只是噪声,被丢弃了 如果要按名称引用记录类型的元素,则需要使用已知类型。创建并使用类型

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

  • “col”字符变化='a'(可以是
    'b'
  • “rec”记录从以下位置保存记录:
    (选择1作为“a”,选择2作为“b”)
  • “res”整数

  • 我需要引用
    “col”
    中来自
    “rec”
    的命名列。因此,如果
    “col”
    具有
    “b”
    ,我将引用
    “rec.”“b”
    ,然后将其值保存到
    “res”

    中,您不能在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
    可以保存任意数据,则需要使用

    演示 使用动态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;
    
    电话:

    返回:

    f_test
    ----
    1
    

    与往常一样,使用中的PostgreSQL版本?@ErwinBrandstetter未指定,因此假设为最新版本。
    f_test
    ----
    1