Sql 函数动态查找列名

Sql 函数动态查找列名,sql,postgresql,plpgsql,dynamic-sql,Sql,Postgresql,Plpgsql,Dynamic Sql,在下面提供的函数find\u value\u In_table()中,我试图找到任何列的名称,这些列的记录中的列值与字符串“255.255.255.255”匹配 简而言之,是这样的: SELECT column_name FROM dynamic_table WHERE column_value = '255.255.255.255'; 注: 表名作为参数传递给函数,因此称为“dynamic_table” 我试图确定列的名称,而不是数据值 这是第一步。稍后我还将参数化列_值。我知道

在下面提供的函数
find\u value\u In_table()
中,我试图找到任何列的名称,这些列的记录中的列值与字符串“255.255.255.255”匹配

简而言之,是这样的:

SELECT column_name
  FROM dynamic_table
  WHERE column_value = '255.255.255.255';
注:

  • 表名作为参数传递给函数,因此称为“dynamic_table”
  • 我试图确定列的名称,而不是数据值
这是第一步。稍后我还将参数化列_值。我知道某个地方有一个存储值的表
“255.255.255.255”
,我想通过查找存储此值的表和列名来证明此函数的功能

这一切的目的是:我有一个大的数据库,我是复古工程。我知道它包含应用程序的一些配置参数。在当前配置中,我知道其中一些参数的精确值(见应用程序配置GUI:例如计算机名、ip地址)。我想浏览整个数据库,以确定哪些表存储此配置信息

我一直在构建函数
find_value()
,以返回这些线索

如何做到这一点

create or replace function find_all_columns(tablename in text) 
    return setof record as
$func$
    declare r record;
    begin 
        return select   a.attname as "Column",
            pg_catalog.format_type(a.atttypid, a.atttypmod) as "Datatype"
            from
            pg_catalog.pg_attribute a
            where
            a.attnum > 0
            and not a.attisdropped
            and a.attrelid = (  select c.oid from pg_catalog.pg_class c left join pg_catalog.pg_namespace n on n.oid = c.relnamespace where c.relname ~ '^('  ||   quote_ident(tablename)    ||   ')$' and pg_catalog.pg_table_is_visible(c.oid);
        end loop;
    end;
$func$ language 'plpgsql';  

create or replace function find_value_in_table(tablename text) 
    returns setof record as 
$func$
    declare r record;
        return select 
    begin 

        for r in (select find_all_columns(tablename)) loop
            return select * from tablename t where t... = "255.255.255.255" /*  here column would be the value in the record: r.Column*/ 
        end loop;
    end;
$func$ language 'plpgsql';

create or replace function find_tables_name(_username text)
  returns setof record as
$func$
declare
   tbl text;
begin
   for tbl in 
      select t.tablename from pg_tables t
      where  t.tableowner = _username and t.schemaname = 'public'
   loop
      return quote_ident(tbl);
   end loop;
end;
$func$ language 'plpgsql';

create or replace function find_value(_username text, valuetofind text) 
    returns setof record as 
$func$
    declare r record;
    begin 
        for r in (select find_tables_name(_username)) loop
            return find_value_in_table( r.tablename );
        end loop;
    end;
$func$ language 'plpgsql';

实现这一点的一种基本方法是进行纯文本转储,并使用您选择的编辑器(在我的例子中是vim)搜索字符串

但是这个函数做得更好。:)

电话:

返回:

       tbl       |     col     | typ
-----------------+-------------+------
 event.eventkat  | eventkat    | text
 public.foo      | description | text
 public.bar      | filter      | text
使用PostgreSQL 9.1进行测试

要点
  • 该功能是一站式的

  • 我构建了一个选项来搜索部分值(
    \u part
    )。默认设置是搜索整列

  • 我在整行上构建了一个快速测试,以消除那些根本没有
    值find
    的表。为此,我使用PostgreSQL的功能将整行快速转换为文本。这将使函数更快—除非所有或几乎所有表都符合条件,或者表只有一列

  • 我将返回类型定义为
    返回表(tbl text、col text、typ text)
    ,并立即分配隐式定义的变量
    tbl
    col
    typ
    。因此,我不需要额外的变量,当列符合条件时,我可以
    立即返回NEXT

  • 在这里大量使用
    存在
    !这是最快的选择,因为您只关心该列是否具有该值

  • 使用
    (或简称
    ~
    )代替正则表达式。更简单,更快

  • I
    quote_ident()
    立即输入所有标识符

  • 是工具性的

。我修复了你的伪代码。
SELECT * FROM find_columns('postgres', '255.255.255.255');
SELECT * FROM find_columns('fadmin', '255.255.255.255', TRUE);
       tbl       |     col     | typ
-----------------+-------------+------
 event.eventkat  | eventkat    | text
 public.foo      | description | text
 public.bar      | filter      | text