从information_schema中查找PostgreSQL中未知表的特定列中的值

时间:2013-12-12 22:58:33

标签: sql postgresql information-schema

使用pl / pgsql我已经将一个更新函数混合在一起运行在一堆我需要更改的表上,但我不知道所有的名字。我所知道的是他们都有一个主键(可以命名为任何东西)和一个专门称为'元数据'的列。例如,其中一个“未知”命名表可能如下所示:

CREATE TABLE test
(
    gid SERIAL NOT NULL PRIMARY KEY,
    item varchar,
    metadata varchar,
    z_order int,
    foobar int
);

我正在尝试返回我更新的每一行(由BEFORE UPDATE触发器创建):

history | action    | table_name | column_name| pkey_id | metadata    |
1       | UPDATE    | test       | item       |       1 |          y  |
_____________________________________________________________________ |
2       | UPDATE    | test       | z_order    |       1 |          y  |
_____________________________________________________________________
3       | UPDATE    | test       | foobar     |       1 |          y  |

但是,我在查询中调用特定的column_name“元数据”时遇到问题...因为id'ing pkey_id(可能有任何列名)我使用了information_schema:

    SELECT
        INTO pkey_column_name
        kcu.column_name
    FROM
        information_schema.table_constraints AS tc
        JOIN information_schema.key_column_usage AS kcu
        ON tc.constraint_name = kcu.constraint_name
        JOIN information_schema.constraint_column_usage AS ccu
        ON ccu.constraint_name = tc.constraint_name
    WHERE
        constraint_type = 'PRIMARY KEY'
    AND
        ccu.table_name=tg_relname;

 /// more code ///
  FOR each_entity IN
     EXECUTE 'SELECT text((' || QUOTE_NULLABLE(OLD) || '::"' || QUOTE_IDENT(tg_table_schema) || '"."' || QUOTE_IDENT(tg_relname) || '")."'  || QUOTE_IDENT(pkey_column_name) || '")
                AS pk_val, 
/// more code ///

但是......我尝试将特定的column_name“元数据”添加到我的执行查询中失败了。理想情况下,我想使用attname按名称选择它...但我没有太多运气...我有一个列的每列('each_column')名称(包括'元数据')但没办法调用它在EXECUTE声明......

FOR each_column IN
    SELECT
        attname as column_name
    FROM
        pg_attribute
    WHERE
        attrelid =
        (
            SELECT
                oid --  'oid' is the internal Postgresql primary key used for various system tables
            FROM
                pg_class
            WHERE
                relname = tg_relname -- 'tg_relname' is a special Trigger variable that gives the name of the table invoking the trigger
        )
    AND attnum > 0 -- returns no system columns 
LOOP

2 个答案:

答案 0 :(得分:0)

而不是:

FOR column_name IN SELECT ...

使用:

SELECT ARRAY(SELECT ...) INTO variable

然后使用array_to_string()进行充分的quote_ident()调用,或者如果您需要有条件或带有where子句,请使用以下内容:

array_to_string((select array(... from unnest(variable) cols where ...)), ',')

这应该允许您根据需要构建任意数量的select或where子句(使用' AND '而不是','),并且可以使用任意数量的潜在条件。

答案 1 :(得分:0)

这就是我提出的建议(感谢Denis的建议)〜

http://www.sqlfiddle.com/#!15/64e41/2/0