从任意%ROWTYPE或RECORD值获取表名

时间:2015-12-09 22:37:46

标签: sql postgresql function plpgsql

期望的设置

为了改善某些代码的优雅,我想知道是否/可能与%ROWTYPE variable from table name相反 - 从<提取表名 / em> a %ROWTYPERECORD(最相关的是,在将其传递到接受ANYELEMENT伪类型的函数后):

CREATE OR REPLACE FUNCTION generic_function(row_data ANYELEMENT)
RETURNS INT AS $$
DECLARE
    table_name TEXT = get_table_name(row_data);
BEGIN
    -- [ work goes here ]
END;
$$ LANGUAGE plpgsql;

当前解决方法

CREATE OR REPLACE FUNCTION generic_function(row_data ANYELEMENT, table_name TEXT) 
RETURNS INT AS $$
BEGIN
    -- [ work goes here ]
END;
$$ LANGUAGE plpgsql;

如果可以想象它在调用代码中的外观,那么解决方法会感觉触摸多余:

SELECT INTO x * FROM mytable WHERE foo = bar; 
PERFORM generic_function(x,'mytable');

优雅但愚蠢的解决方案

为了允许我显示的呼叫签名,我能提出的最佳解决方案是一种高开销的猜测和检查方法,这可能是非常坏主意用于生产。你可以找到sqlfiddle here

2 个答案:

答案 0 :(得分:1)

有一个简单的解决方案。使用pg_typeof()

CREATE OR REPLACE FUNCTION generic_function(row_data ANYELEMENT)
  RETURNS text AS
$func$
DECLARE
   table_name text := pg_typeof($1);
BEGIN
   RETURN table_name;
END
$func$ LANGUAGE plpgsql;

显然,这只适用于已注册的复合类型。 每个表或视图都属于此类别。但不是派生表。

测试:

CREATE TEMP TABLE foo (id int);
SELECT generic_function(NULL::foo);

Here is a search for related answers.

答案 1 :(得分:0)

plpgsql级别没有任何解决方案。从理论上讲,你可以在C扩展中的某些情况下执行它,但代码将非常复杂。 Postgres,PLpgSQL被设计为静态的,类型刚性的环境 - 动态SQL不会过多地改变它(设计更喜欢速度,更少的内存使用)。只是不要在Postgres中设计过于动态的代码。