2016-11-18 53 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; 
$$;