Wie suche ich einen bestimmten Wert in allen Tabellen (PostgreSQL)?

110

Ist es möglich, jede Spalte jeder Tabelle nach einem bestimmten Wert in PostgreSQL zu durchsuchen ?

Eine ähnliche Frage ist hier für Oracle verfügbar .

Sandro Munda
quelle
Suchen Sie ein Tool oder eine Implementierung der in der verknüpften Frage gezeigten Verfahren?
a_horse_with_no_name
Nein, nur der einfachste Weg, einen bestimmten Wert in allen Feldern / Tabellen zu finden.
Sandro Munda
Sie möchten also kein externes Tool verwenden?
a_horse_with_no_name
1
Wenn es der einfachste Weg ist => ok für ein externes Tool :-)
Sandro Munda

Antworten:

131

Wie wäre es, den Inhalt der Datenbank zu sichern und dann zu verwenden grep?

$ pg_dump --data-only --inserts -U postgres your-db-name > a.tmp
$ grep United a.tmp
INSERT INTO countries VALUES ('US', 'United States');
INSERT INTO countries VALUES ('GB', 'United Kingdom');

Das gleiche Dienstprogramm, pg_dump, kann Spaltennamen in die Ausgabe aufnehmen. Wechseln Sie einfach --insertszu --column-inserts. Auf diese Weise können Sie auch nach bestimmten Spaltennamen suchen. Aber wenn ich nach Spaltennamen suchen würde, würde ich wahrscheinlich das Schema anstelle der Daten ausgeben.

$ pg_dump --data-only --column-inserts -U postgres your-db-name > a.tmp
$ grep country_code a.tmp
INSERT INTO countries (iso_country_code, iso_country_name) VALUES ('US', 'United  States');
INSERT INTO countries (iso_country_code, iso_country_name) VALUES ('GB', 'United Kingdom');
Mike Sherrill 'Cat Recall'
quelle
5
+1 kostenlos und einfach. Und wenn Sie Struktur wollen, kann pg_dump das auch. Auch wenn grep nicht Ihr Ding ist, verwenden Sie das gewünschte Tool zur Suche nach Dateiinhalten für die ausgelagerten Strukturen und / oder Daten.
Kuberchaun
Wenn Sie Textdaten (die normalerweise in neueren Versionen von Postgres codiert sind) erfassen möchten, müssen Sie sie möglicherweise in ALTER DATABASE your_db_name SET bytea_output = 'escape';der Datenbank (oder einer Kopie davon) speichern, bevor Sie sie sichern können . (Ich sehe keine Möglichkeit, dies nur für einen pg_dumpBefehl anzugeben .)
Phils
können Sie im Detail erklären ..? Wie suche ich die Zeichenfolge 'ABC' in alle Tabellen?
Herr Bhosale
1
Wenn Sie IntelliJ verwenden, können Sie einfach mit der rechten Maustaste auf Ihre Datenbank klicken und "Dump with 'pg_dump'" oder "Dump data to file (s)"
Laurens
3
Wie ist dies eine gültige Lösung für eine Datenbank, die so groß ist, dass Sie sie nicht auf Ihre Festplatte kopieren können?
Govind Parmar
76

Hier ist eine pl / pgsql-Funktion , die Datensätze findet, in denen eine Spalte einen bestimmten Wert enthält. Als Argumente werden der zu suchende Wert im Textformat, ein Array von Tabellennamen, nach denen gesucht werden soll (standardmäßig alle Tabellen) und ein Array von Schemanamen (standardmäßig alle Schemanamen) verwendet.

Es gibt eine Tabellenstruktur mit Schema, Name der Tabelle, Name der Spalte und Pseudospalte zurück ctid(nicht dauerhafte physische Position der Zeile in der Tabelle, siehe Systemspalten ).

CREATE OR REPLACE FUNCTION search_columns(
    needle text,
    haystack_tables name[] default '{}',
    haystack_schema name[] default '{}'
)
RETURNS table(schemaname text, tablename text, columnname text, rowctid text)
AS $$
begin
  FOR schemaname,tablename,columnname IN
      SELECT c.table_schema,c.table_name,c.column_name
      FROM information_schema.columns c
        JOIN information_schema.tables t ON
          (t.table_name=c.table_name AND t.table_schema=c.table_schema)
        JOIN information_schema.table_privileges p ON
          (t.table_name=p.table_name AND t.table_schema=p.table_schema
              AND p.privilege_type='SELECT')
        JOIN information_schema.schemata s ON
          (s.schema_name=t.table_schema)
      WHERE (c.table_name=ANY(haystack_tables) OR haystack_tables='{}')
        AND (c.table_schema=ANY(haystack_schema) OR haystack_schema='{}')
        AND t.table_type='BASE TABLE'
  LOOP
    FOR rowctid IN
      EXECUTE format('SELECT ctid FROM %I.%I WHERE cast(%I as text)=%L',
       schemaname,
       tablename,
       columnname,
       needle
      )
    LOOP
      -- uncomment next line to get some progress report
      -- RAISE NOTICE 'hit in %.%', schemaname, tablename;
      RETURN NEXT;
    END LOOP;
 END LOOP;
END;
$$ language plpgsql;

Siehe auch die Version auf Github, die auf demselben Prinzip basiert, aber einige Geschwindigkeits- und Berichtsverbesserungen hinzufügt.

Anwendungsbeispiele in einer Testdatenbank:

  • Suchen Sie in allen Tabellen im öffentlichen Schema:
Wählen Sie * aus search_columns ('foobar').
 Schemaname | Tabellenname | Spaltenname | Rowctid
------------ + ----------- + ------------ + ---------
 public | s3 | Benutzername | (0,11)
 public | s2 | relname | (7,29)
 public | w | Körper | (0,2)
(3 Reihen)
  • Suche in einer bestimmten Tabelle:
 Wählen Sie * aus search_columns ('foobar', '{w}').
 Schemaname | Tabellenname | Spaltenname | Rowctid
------------ + ----------- + ------------ + ---------
 public | w | Körper | (0,2)
(1 Reihe)
  • Suchen Sie in einer Teilmenge von Tabellen, die Sie aus einer Auswahl erhalten haben:
select * from search_columns ('foobar', array (wähle table_name :: name aus information_schema.tables, wobei table_name wie 's%' ist), array ['public']);
 Schemaname | Tabellenname | Spaltenname | Rowctid
------------ + ----------- + ------------ + ---------
 public | s2 | relname | (7,29)
 public | s3 | Benutzername | (0,11)
(2 Reihen)
  • Holen Sie sich eine Ergebniszeile mit der entsprechenden Basistabelle und und ctid:
wähle * aus public.w wobei ctid = '(0,2)';
 Titel | Körper | tsv         
------- + -------- + ---------------------
 toto | foobar | 'foobar': 2 'toto': 1

Varianten

  • Um diesen Teil der Abfrage anhand eines regulären Ausdrucks anstelle einer strengen Gleichheit wie grep zu testen:

    SELECT ctid FROM %I.%I WHERE cast(%I as text)=%L

    kann geändert werden in:

    SELECT ctid FROM %I.%I WHERE cast(%I as text) ~ %L

  • Für Vergleiche ohne Berücksichtigung der Groß- und Kleinschreibung können Sie Folgendes schreiben:

    SELECT ctid FROM %I.%I WHERE lower(cast(%I as text)) = lower(%L)

Daniel Vérité
quelle
FEHLER: Syntaxfehler bei oder nahe "Standard" LINE 3: haystack_tables name [] default '{}' (Verwenden von PostgreSQL 8.2.17 und kein Upgrade möglich)
Henno
@ Henno: Ja, es erfordert PG-9.1. Jetzt bearbeitet, um dies explizit zu machen. Um es mit älteren Versionen zu verwenden, müssen Sie es anpassen.
Daniel Vérité
1
@Rajendra_Prasad: Der Operator für reguläre Ausdrücke hat eine Variante, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird: ~*angemessener als niedriger (). Aber das t.*ist sowieso nicht Teil der obigen Antwort. Das spaltenweise Suchen ist aufgrund der Spaltentrennzeichen nicht dasselbe wie das Durchsuchen der Zeile als Wert.
Daniel Vérité
2
Dies gibt nur eine Zeile pro Schematabellenspalte zurück.
theGtknerd
1
Vielen Dank. Diese Lösung funktioniert perfekt für mich. Ich musste eine Tabelle in einer Liste von mehr als 1000 Tabellen finden, die eine bestimmte URL enthält. Du hast meinen Tag gerettet!.
Sunil
7

um jede Spalte jeder Tabelle nach einem bestimmten Wert zu durchsuchen

Dies definiert nicht, wie genau übereinstimmen soll.
Es definiert auch nicht, was genau zurückgegeben werden soll.

Angenommen:

  • Finde jede Zeile mit jeder Spalte enthält den gegebenen Wert in seiner Textdarstellung - im Gegensatz zu gleich dem angegebenen Wert.
  • Geben Sie den Tabellennamen ( regclass) und die Tupel-ID ( ctid) zurück, da dies am einfachsten ist.

Hier ist eine absolut einfache, schnelle und leicht schmutzige Art:

CREATE OR REPLACE FUNCTION search_whole_db(_like_pattern text)
  RETURNS TABLE(_tbl regclass, _ctid tid) AS
$func$
BEGIN
   FOR _tbl IN
      SELECT c.oid::regclass
      FROM   pg_class c
      JOIN   pg_namespace n ON n.oid = relnamespace
      WHERE  c.relkind = 'r'                           -- only tables
      AND    n.nspname !~ '^(pg_|information_schema)'  -- exclude system schemas
      ORDER BY n.nspname, c.relname
   LOOP
      RETURN QUERY EXECUTE format(
         'SELECT $1, ctid FROM %s t WHERE t::text ~~ %L'
       , _tbl, '%' || _like_pattern || '%')
      USING _tbl;
   END LOOP;
END
$func$  LANGUAGE plpgsql;

Anruf:

SELECT * FROM search_whole_db('mypattern');

Geben Sie das Suchmuster ohne Beilage an %.

Warum etwas schmutzig?

Wenn Trennzeichen und Dekoratoren für die dargestellte Zeile textTeil des Suchmusters sein können, kann es zu Fehlalarmen kommen:

  • Spaltentrennzeichen: ,Standardmäßig
  • Die ganze Zeile ist in Klammern eingeschlossen:()
  • Einige Werte sind in doppelte Anführungszeichen gesetzt "
  • \ kann als Escape-Zeichen hinzugefügt werden

Und die Textdarstellung einiger Spalten hängt möglicherweise von den lokalen Einstellungen ab - aber diese Mehrdeutigkeit ist der Frage inhärent, nicht meiner Lösung.

Jede qualifizierende Zeile wird nur einmal zurückgegeben , auch wenn sie mehrmals übereinstimmt (im Gegensatz zu anderen Antworten hier).

Dadurch wird die gesamte Datenbank mit Ausnahme der Systemkataloge durchsucht. Die Fertigstellung dauert normalerweise lange . Möglicherweise möchten Sie sich auf bestimmte Schemas / Tabellen (oder sogar Spalten) beschränken, wie in anderen Antworten gezeigt. Oder fügen Sie Hinweise und eine Fortschrittsanzeige hinzu, die auch in einer anderen Antwort gezeigt werden.

Der regclassObjektkennungstyp wird als Tabellenname dargestellt, der bei Bedarf schemaqualifiziert ist, um gemäß dem aktuellen Wert zu unterscheiden search_path:

Was ist das ctid?

Möglicherweise möchten Sie Zeichen mit besonderer Bedeutung im Suchmuster maskieren. Sehen:

Erwin Brandstetter
quelle
Diese großartige Lösung ist sogar noch besser mit niedriger () - 'SELECT $ 1, ctid FROM% st WHERE niedriger (t :: text) ~~ niedriger (% L)'
Georgi Bonchev
5

Und wenn jemand denkt, es könnte helfen. Hier ist die Funktion von @Daniel Vérité mit einem weiteren Parameter, der Namen von Spalten akzeptiert, die für die Suche verwendet werden können. Auf diese Weise wird die Verarbeitungszeit verkürzt. Zumindest in meinem Test hat es sich stark reduziert.

CREATE OR REPLACE FUNCTION search_columns(
    needle text,
    haystack_columns name[] default '{}',
    haystack_tables name[] default '{}',
    haystack_schema name[] default '{public}'
)
RETURNS table(schemaname text, tablename text, columnname text, rowctid text)
AS $$
begin
  FOR schemaname,tablename,columnname IN
      SELECT c.table_schema,c.table_name,c.column_name
      FROM information_schema.columns c
      JOIN information_schema.tables t ON
        (t.table_name=c.table_name AND t.table_schema=c.table_schema)
      WHERE (c.table_name=ANY(haystack_tables) OR haystack_tables='{}')
        AND c.table_schema=ANY(haystack_schema)
        AND (c.column_name=ANY(haystack_columns) OR haystack_columns='{}')
        AND t.table_type='BASE TABLE'
  LOOP
    EXECUTE format('SELECT ctid FROM %I.%I WHERE cast(%I as text)=%L',
       schemaname,
       tablename,
       columnname,
       needle
    ) INTO rowctid;
    IF rowctid is not null THEN
      RETURN NEXT;
    END IF;
 END LOOP;
END;
$$ language plpgsql;

Unten ist ein Beispiel für die Verwendung der oben erstellten Suchfunktion.

SELECT * FROM search_columns('86192700'
    , array(SELECT DISTINCT a.column_name::name FROM information_schema.columns AS a
            INNER JOIN information_schema.tables as b ON (b.table_catalog = a.table_catalog AND b.table_schema = a.table_schema AND b.table_name = a.table_name)
        WHERE 
            a.column_name iLIKE '%cep%' 
            AND b.table_type = 'BASE TABLE'
            AND b.table_schema = 'public'
    )

    , array(SELECT b.table_name::name FROM information_schema.columns AS a
            INNER JOIN information_schema.tables as b ON (b.table_catalog = a.table_catalog AND b.table_schema = a.table_schema AND b.table_name = a.table_name)
        WHERE 
            a.column_name iLIKE '%cep%' 
            AND b.table_type = 'BASE TABLE'
            AND b.table_schema = 'public')
);
Daniel A. Martinhao
quelle
5

Ohne eine neue Prozedur zu speichern, können Sie einen Codeblock verwenden und ausführen, um eine Tabelle mit Vorkommen zu erhalten. Sie können Ergebnisse nach Schema-, Tabellen- oder Spaltennamen filtern.

DO $$
DECLARE
  value int := 0;
  sql text := 'The constructed select statement';
  rec1 record;
  rec2 record;
BEGIN
  DROP TABLE IF EXISTS _x;
  CREATE TEMPORARY TABLE _x (
    schema_name text, 
    table_name text, 
    column_name text,
    found text
  );
  FOR rec1 IN 
        SELECT table_schema, table_name, column_name
        FROM information_schema.columns 
        WHERE table_name <> '_x'
                AND UPPER(column_name) LIKE UPPER('%%')                  
                AND table_schema <> 'pg_catalog'
                AND table_schema <> 'information_schema'
                AND data_type IN ('character varying', 'text', 'character', 'char', 'varchar')
        LOOP
    sql := concat('SELECT ', rec1."column_name", ' AS "found" FROM ',rec1."table_schema" , '.',rec1."table_name" , ' WHERE UPPER(',rec1."column_name" , ') LIKE UPPER(''','%my_substring_to_find_goes_here%' , ''')');
    RAISE NOTICE '%', sql;
    BEGIN
        FOR rec2 IN EXECUTE sql LOOP
            RAISE NOTICE '%', sql;
            INSERT INTO _x VALUES (rec1."table_schema", rec1."table_name", rec1."column_name", rec2."found");
        END LOOP;
    EXCEPTION WHEN OTHERS THEN
    END;
  END LOOP;
  END; $$;

SELECT * FROM _x;
profimedica
quelle
Wo geben Sie die Suchzeichenfolge an? Oder wird nur die gesamte Datenbank Tabelle für Tabelle ausgegeben?
Jimtut
1
Ich habe keinen Parameter für die Zeichenfolge erstellt. Sie können es entweder fest codieren und direkt als Block ausführen oder eine gespeicherte Prozedur daraus erstellen. In jedem Fall liegt Ihre zu suchende Zeichenfolge hier zwischen den beiden Prozentzeichen: WHERE UPPER (', rec1. "Column_name",') LIKE UPPER ('' ',' %% ',' '')
profimedica
5

Es gibt eine Möglichkeit, dies zu erreichen, ohne eine Funktion zu erstellen oder ein externes Tool zu verwenden. Durch die Verwendung der Postgres- query_to_xml()Funktion, mit der eine Abfrage dynamisch in einer anderen Abfrage ausgeführt werden kann, kann ein Text in vielen Tabellen durchsucht werden. Dies basiert auf meiner Antwort , um die Zeilenanzahl für alle Tabellen abzurufen :

Um fooin allen Tabellen eines Schemas nach der Zeichenfolge zu suchen , können Sie Folgendes verwenden:

with found_rows as (
  select format('%I.%I', table_schema, table_name) as table_name,
         query_to_xml(format('select to_jsonb(t) as table_row 
                              from %I.%I as t 
                              where t::text like ''%%foo%%'' ', table_schema, table_name), 
                      true, false, '') as table_rows
  from information_schema.tables 
  where table_schema = 'public'
)
select table_name, x.table_row
from found_rows f
  left join xmltable('//table/row' 
                     passing table_rows
                       columns
                         table_row text path 'table_row') as x on true

Beachten Sie, dass für die Verwendung von xmltablePostgres 10 oder neuer erforderlich ist. Bei älteren Postgres-Versionen kann dies auch mit xpath () erfolgen.

with found_rows as (
  select format('%I.%I', table_schema, table_name) as table_name,
         query_to_xml(format('select to_jsonb(t) as table_row 
                              from %I.%I as t 
                              where t::text like ''%%foo%%'' ', table_schema, table_name), 
                      true, false, '') as table_rows
  from information_schema.tables 
  where table_schema = 'public'
)
select table_name, x.table_row
from found_rows f
   cross join unnest(xpath('/table/row/table_row/text()', table_rows)) as r(data)

Der allgemeine Tabellenausdruck ( WITH ...) wird nur zur Vereinfachung verwendet. Es durchläuft alle Tabellen im publicSchema. Für jede Tabelle wird die folgende Abfrage über die query_to_xml()Funktion ausgeführt:

select to_jsonb(t)
from some_table t
where t::text like '%foo%';

Die where-Klausel wird verwendet, um sicherzustellen, dass die teure Generierung von XML-Inhalten nur für Zeilen erfolgt, die die Suchzeichenfolge enthalten. Dies könnte etwa Folgendes zurückgeben:

<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
  <table_row>{"id": 42, "some_column": "foobar"}</table_row>
</row>
</table>

Die Konvertierung der gesamten Zeile in jsonberfolgt, so dass im Ergebnis zu sehen ist, welcher Wert zu welcher Spalte gehört.

Das Obige könnte etwa Folgendes zurückgeben:

table_name   |   table_row
-------------+----------------------------------------
public.foo   |  {"id": 1, "some_column": "foobar"}
public.bar   |  {"id": 42, "another_column": "barfoo"}

Online-Beispiel für Postgres 10+

Online-Beispiel für ältere Postgres-Versionen

ein Pferd ohne Name
quelle
Ich versuche, den Code für ältere PostgreSQL-Versionen auszuführen, und erhalte die folgende FehlermeldungERROR: 42883: function format("unknown", information_schema.sql_identifier, information_schema.sql_identifier) does not exist
Matt
Sie müssen sie wahrscheinlich format('%I.%I', table_schema::text, table_name::text)
besetzen
Ok, getan, jetzt habe ichERROR: 42883: function format("unknown", character varying, character varying) does not exist
Matt
Dann sind viele Ihrer Postgres-Versionen so alt, dass die ID nicht einmal die format()Funktion hat
a_horse_with_no_name
Ich denke Redshift basiert auf 8.3?
Matt
3

Hier ist die Funktion von @Daniel Vérité mit Funktionen zur Fortschrittsberichterstattung. Es gibt Fortschritte auf drei Arten:

  1. durch RAISE NOTICE;
  2. durch Verringern des Werts der angegebenen {progress_seq} -Sequenz von {Gesamtzahl der zu suchenden Spalten} auf 0;
  3. indem Sie den Fortschritt zusammen mit den gefundenen Tabellen in eine Textdatei schreiben, die sich in c: \ windows \ temp \ {progress_seq} .txt befindet.

_

CREATE OR REPLACE FUNCTION search_columns(
    needle text,
    haystack_tables name[] default '{}',
    haystack_schema name[] default '{public}',
    progress_seq text default NULL
)
RETURNS table(schemaname text, tablename text, columnname text, rowctid text)
AS $$
DECLARE
currenttable text;
columnscount integer;
foundintables text[];
foundincolumns text[];
begin
currenttable='';
columnscount = (SELECT count(1)
      FROM information_schema.columns c
      JOIN information_schema.tables t ON
        (t.table_name=c.table_name AND t.table_schema=c.table_schema)
      WHERE (c.table_name=ANY(haystack_tables) OR haystack_tables='{}')
        AND c.table_schema=ANY(haystack_schema)
        AND t.table_type='BASE TABLE')::integer;
PERFORM setval(progress_seq::regclass, columnscount);

  FOR schemaname,tablename,columnname IN
      SELECT c.table_schema,c.table_name,c.column_name
      FROM information_schema.columns c
      JOIN information_schema.tables t ON
        (t.table_name=c.table_name AND t.table_schema=c.table_schema)
      WHERE (c.table_name=ANY(haystack_tables) OR haystack_tables='{}')
        AND c.table_schema=ANY(haystack_schema)
        AND t.table_type='BASE TABLE'
  LOOP
    EXECUTE format('SELECT ctid FROM %I.%I WHERE cast(%I as text)=%L',
       schemaname,
       tablename,
       columnname,
       needle
    ) INTO rowctid;
    IF rowctid is not null THEN
      RETURN NEXT;
      foundintables = foundintables || tablename;
      foundincolumns = foundincolumns || columnname;
      RAISE NOTICE 'FOUND! %, %, %, %', schemaname,tablename,columnname, rowctid;
    END IF;
         IF (progress_seq IS NOT NULL) THEN 
        PERFORM nextval(progress_seq::regclass);
    END IF;
    IF(currenttable<>tablename) THEN  
    currenttable=tablename;
     IF (progress_seq IS NOT NULL) THEN 
        RAISE NOTICE 'Columns left to look in: %; looking in table: %', currval(progress_seq::regclass), tablename;
        EXECUTE 'COPY (SELECT unnest(string_to_array(''Current table (column ' || columnscount-currval(progress_seq::regclass) || ' of ' || columnscount || '): ' || tablename || '\n\nFound in tables/columns:\n' || COALESCE(
        (SELECT string_agg(c1 || '/' || c2, '\n') FROM (SELECT unnest(foundintables) AS c1,unnest(foundincolumns) AS c2) AS t1)
        , '') || ''',''\n''))) TO ''c:\WINDOWS\temp\' || progress_seq || '.txt''';
    END IF;
    END IF;
 END LOOP;
END;
$$ language plpgsql;
alexkovelsky
quelle
3

- Die folgende Funktion listet alle Tabellen auf, die eine bestimmte Zeichenfolge in der Datenbank enthalten

 select TablesCount(‘StringToSearch’);

- Durchläuft alle Tabellen in der Datenbank

CREATE OR REPLACE FUNCTION **TablesCount**(_searchText TEXT)
RETURNS text AS 
$$ -- here start procedural part
   DECLARE _tname text;
   DECLARE cnt int;
   BEGIN
    FOR _tname IN SELECT table_name FROM information_schema.tables where table_schema='public' and table_type='BASE TABLE'  LOOP
         cnt= getMatchingCount(_tname,Columnames(_tname,_searchText));
                                RAISE NOTICE 'Count% ', CONCAT('  ',cnt,' Table name: ', _tname);
                END LOOP;
    RETURN _tname;
   END;
$$ -- here finish procedural part
LANGUAGE plpgsql; -- language specification

- Gibt die Anzahl der Tabellen zurück, für die die Bedingung erfüllt ist. - Wenn beispielsweise der beabsichtigte Text in einem der Felder der Tabelle vorhanden ist, - ist die Anzahl größer als 0. Die Benachrichtigungen finden Sie im Abschnitt "Nachrichten" des Ergebnisbetrachters in der Postgres-Datenbank.

CREATE OR REPLACE FUNCTION **getMatchingCount**(_tname TEXT, _clause TEXT)
RETURNS int AS 
$$
Declare outpt text;
    BEGIN
    EXECUTE 'Select Count(*) from '||_tname||' where '|| _clause
       INTO outpt;
       RETURN outpt;
    END;
$$ LANGUAGE plpgsql;

- Holen Sie sich die Felder jeder Tabelle. Erstellt die where-Klausel mit allen Spalten einer Tabelle.

CREATE OR REPLACE FUNCTION **Columnames**(_tname text,st text)
RETURNS text AS 
$$ -- here start procedural part
DECLARE
                _name text;
                _helper text;
   BEGIN
                FOR _name IN SELECT column_name FROM information_schema.Columns WHERE table_name =_tname LOOP
                                _name=CONCAT('CAST(',_name,' as VarChar)',' like ','''%',st,'%''', ' OR ');
                                _helper= CONCAT(_helper,_name,' ');
                END LOOP;
                RETURN CONCAT(_helper, ' 1=2');

   END;
$$ -- here finish procedural part
LANGUAGE plpgsql; -- language specification
Ganesh
quelle