postgresql,无法识别记录数据类型中的列

时间:2016-11-18 15:06:40

标签: postgresql dynamic-sql execute

我尝试使用Postgresql动态SQL。我试图在另一个id声明中使用db_row RECORD中的EXECUTE字段。字段id在记录变量中设置但我仍然收到错误:

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的完整结构,就像porfolio表中的行一样。

我的最终目标是创建将采用任何现有表名的函数 这样做:

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在此db_row.id语句中使用EXECUTE值?

1 个答案:

答案 0 :(得分:1)

问题是您将类型db_row的参数(record)传递给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;
$$;