2016-11-18 77 views
0

我正在尝试对Postgresql使用动态SQL。我坚持尝试使用另一个EXECUTE声明中的db_row RECORD中的id字段。现场id设置在创纪录的变量,但我仍然得到错误:postgresql,无法识别记录数据类型中的列

ERROR: could not identify column "id" in record data type 
LINE 1: SELECT $1.id FROM audit.portfolio WHERE alter_type = 'INSERT... 
      ^
QUERY: SELECT $1.id FROM audit.portfolio WHERE alter_type = 'INSERT' AND id = $1.id 
CONTEXT: PL/pgSQL function inline_code_block line 14 at EXECUTE 

这是我的数据和测试功能:

CREATE TABLE IF NOT EXISTS public.portfolio 
(
    id INTEGER NOT NULL, 
    name CHARACTER VARYING, 
    CONSTRAINT portfolio_pkey PRIMARY KEY (id) 
) 
WITH (OIDS = FALSE); 

CREATE TABLE IF NOT EXISTS audit.portfolio 
(
    alter_type TEXT, 
    id   INTEGER NOT NULL, 
    name  CHARACTER VARYING, 
    CONSTRAINT portfolio_pkey PRIMARY KEY (id) 
) 
WITH (OIDS = FALSE 
); 

INSERT INTO public.portfolio (id, name) VALUES (1, 'NAME 1'), (2, 'NAME 2'); 

-- temp function 
DO $$ 
DECLARE 
    db_row RECORD; 
    pk_val BIGINT; 

BEGIN 

    FOR db_row IN EXECUTE format(
     'SELECT *, 100 AS created_by_id, %L::TIMESTAMP AS creation_time FROM public.%I ORDER BY %I', 
     '2014-01-01 00:00:00', 'portfolio', 'id', 'id') 
    LOOP 
    RAISE NOTICE 'db_row.id: %', db_row.id; 
    EXECUTE 
    format(
     'SELECT $1.%I FROM audit.%I WHERE alter_type = %L AND %I = $1.%I', 
     'id', -- this will be dynamic and change when table change 
     'portfolio', -- this will be dynamic and change when table change 
     'INSERT', 
     'id', -- this will be dynamic and change when table change 
     'id' -- this will be dynamic and change when table change 
    ) 
    INTO pk_val 
    USING db_row; 
    RAISE NOTICE 'pk_val: %', pk_val; 
    END LOOP; 
END$$; 

好像Postgres的EXECUTE ... USING db_row没有看到的db_row就是喜欢完整结构从表中排。

我的最终目标是创造功能,将采取任何现有的表名 做到这一点:

EXECUTE 
    format(
     'SELECT $1.%I FROM audit.%I WHERE alter_type = %L AND %I = $1.%I', 
     'primary_key_col', 
     'table_name', 
     'INSERT', 
     'primary_key_col', 
     'primary_key_col' 
    ) 
    INTO pk_val 
    USING db_row 

如何知道的Postgres在此EXECUTE语句中使用db_row.id价值?

+0

这也许可以提供帮助。 http://stackoverflow.com/questions/14065271/how-to-use-execute-format-using-in-postgres-function – McNets

+0

在这个例子中,我知道表名,列和主键的名称。但在真实的代码中,我不会。所以我不能使用'USING db_row.id,db_row.col2'等。 – piotrekkr

回答

1

问题是您正在将record类型的参数(db_row)传递给SQL语句,但是这样的值没有SQL引擎的已知结构。你甚至不能将它转换为表格类型。

一个丑陋的解决方法我可以想到它将该记录转换为其文本表示形式(它与对类型输出函数的调用一起使用),然后将测试转换为所需的表类型。

这是示例代码,说明我的意思:

DO $$ 
DECLARE 
    r record; 
    n name; 
BEGIN 
    /* find all tables with a column "oid" */ 
    FOR r IN 
     SELECT t.* 
     FROM pg_class t 
       JOIN pg_attribute a ON a.attrelid = t.oid 
     WHERE a.attname = 'oid' 
    LOOP 
     /* get the table name */ 
     EXECUTE format(
       'SELECT ($1::text::%s).relname', 
       'pg_class' 
      ) INTO n USING r; 
     RAISE NOTICE 'Table name: %', n; 
    END LOOP; 
END; 
$$;