it-swarm.com.de

Überprüfen Sie, ob die Sequenz in Postgres (plpgsql) vorhanden ist.

Ich versuche innerhalb einer gespeicherten Prozedur zu testen, ob bereits eine Sequenz vorhanden ist.

IF EXISTS SEQUENCE seq_name
    RAISE EXCEPTION 'sequence % already exists!', seq_name
END IF;

Ich habe mehrere Variationen des obigen Ausschnitts ohne Glück versucht. Ich muss Google die falschen Bedingungen geben, da ich anscheinend nichts zu dem Thema finden kann. Jede Hilfe wird geschätzt!

20
Ilia Choly

Sie sollten in der Lage sein, die Tabelle pg_class abzufragen, um festzustellen, ob der relname vorhanden ist.

IF EXISTS (SELECT 0 FROM pg_class where relname = '<my sequence name here>' )
THEN
  --stuff here
END IF;
20
rfusca

Die Antwort von @rfusca funktioniert, wenn Sie sicher sind, dass der Name nur für eine Sequenz gültig sein könnte (dh Sie sind sicher, dass er nicht für normale Tabellen, Indizes, Ansichten, Verbundtypen, TOAST-Tabellen oder fremde Tabelle), und Sie brauchen sich nicht um mehrere Schemata zu kümmern. Mit anderen Worten, es funktioniert in den meisten Fällen, aber es ist nicht ganz streng.

Wenn Sie testen möchten, ob eine Folge mit diesem Namen in einem bestimmten Schema vorhanden ist, sollte dies funktionieren:

-- Clear the search path so that the regclass of the sequence
-- will be schema-qualified.
SET search_path = '';
-- Do your conditional code.
IF EXISTS (SELECT * FROM pg_class
             WHERE relkind = 'S'
               AND oid::regclass::text = 'public.' || quote_ident(seq_name))
  THEN
    RAISE EXCEPTION 'sequence public.% already exists!', seq_name
END IF;
-- Restore the normal search path.
RESET search_path;
18
kgrittn

Update: Mit to_regclass() in Postgres 9.4 ist es einfach einfacher auf Existenz zu testen.

SELECT to_regclass('schema_name.table_name');

Aber lesen Sie die Details:

Komplette Funktion

Sie müssen nach any tabellenartigen Objekten suchen, die mit dem Namen und nicht nur mit Sequenzen in Konflikt stehen.

Diese Funktion erstellt eine neue Sequenz, wenn der Name verfügbar ist, und gibt in anderen Fällen eine sinnvolle NOTICE/WARNING/EXCEPTION aus:

CREATE OR REPLACE FUNCTION f_create_seq(_seq text, _schema text = NULL)
  RETURNS void AS
$func$
DECLARE
   _fullname text := format('%I.%I', COALESCE(_schema,current_schema),_seq);
   _relkind "char" := (SELECT c.relkind
                       FROM   pg_namespace n
                       JOIN   pg_class c ON c.relnamespace = n.oid
                       WHERE  n.nspname = COALESCE(_schema, current_schema)
                       AND    c.relname = _seq);
BEGIN
   IF _relkind IS NULL THEN   -- name is free
      EXECUTE 'CREATE SEQUENCE ' || _fullname;
      RAISE NOTICE 'New sequence % created.', _fullname;

   ELSIF _relkind = 'S' THEN  -- 'S' = sequence
      IF has_sequence_privilege(_fullname, 'USAGE') THEN
         RAISE WARNING 'Sequence % already exists.', _fullname;
      ELSE
         RAISE EXCEPTION
           'Sequence % already exists but you have no USAGE privilege.'
         , _fullname;
      END IF;

   ELSE
      RAISE EXCEPTION 'A(n) "%" named % already exists.'
      -- Table-like objects in pg 9.4:
      -- www.postgresql.org/docs/current/static/catalog-pg-class.html
         , CASE _relkind WHEN 'r' THEN 'ordinary table'
                         WHEN 'i' THEN 'index'
                      -- WHEN 'S' THEN 'sequence'  -- impossible here
                         WHEN 'v' THEN 'view'
                         WHEN 'm' THEN 'materialized view'
                         WHEN 'c' THEN 'composite type'
                         WHEN 't' THEN 'TOAST table'
                         WHEN 'f' THEN 'foreign table'
                         ELSE 'unknown object' END
         , _fullname;
   END IF;
END
$func$  LANGUAGE plpgsql;

COMMENT ON FUNCTION f_create_seq(text, text) IS
'Create sequence if name is free.
RAISE NOTICE on successful creation.
RAISE WARNING if it already exists.
RAISE EXCEPTION if it already exists and current user lacks USAGE privilege.
RAISE EXCEPTION if object of a different kind occupies the name.
$1 _seq    .. sequence name 
$2 _schema .. schema name (optional; default is CURRENT_SCHEMA)';

Anruf:

SELECT f_create_seq('myseq', 'myschema');

Oder:

SELECT f_create_seq('myseq1');  -- defaults to current schema

Erklären

  • Lesen Sie auch den Kommentar zur Funktion am Ende des Codes.

  • Funktioniert in Postgres 9.1+ . Bei älteren Versionen müssen Sie lediglich format() ersetzen - dies schützt gegen die SQL-Injection. Einzelheiten:

  • Zwei separate Parameter lassen Sequenzen in jedem Schema unabhängig vom aktuellen search_path zu und ermöglichen quote_ident(), ihre Arbeit zu erledigen. quote_ident() schlägt mit schemaqualifizierten Namen fehl - wäre mehrdeutig.

  • Es gibt einen Standardwert für den Schemaparameter, so dass Sie ihn beim Aufruf auslassen können. Wenn kein Schema angegeben ist, verwendet die Funktion standardmäßig den current_schema. Pro Dokumentation:

    current_schema gibt den Namen des Schemas zurück, das sich zuerst im Suchpfad befindet (oder einen Nullwert, wenn der Suchpfad leer ist). Dies ist das Schema , Das für Tabellen oder andere benannte Objekte verwendet wird, die Ohne Angabe eines Zielschemas erstellt werden.

  • Liste der Typen für pgclass.relkind im Handbuch .

  • PostgreSQL-Fehlercodes .

12

So verwenden Sie das Informationsschema:

SELECT COUNT(*) 
FROM information_schema.sequences 
WHERE sequence_schema=? AND sequence_name=?
6
Dave Kok
select relname, relnamespace
from pg_class join pg_catalog.pg_namespace n ON n.oid = pg_class.relnamespace
where n.nspname='metastore_1' and relname='updater_state_id_seq';

Ergebnis:

       relname        | relnamespace 
-------------------------------------
 updater_state_id_seq |        32898

Diese Abfrage kann das Vorhandensein einer Sequenz in einem Schema überprüfen.

1
xingang

Ich bin mir nicht sicher, inwieweit das Vorhandensein der Sequenz überprüft werden muss. Eine Alternative, wenn vor dem Erstellen geprüft werden soll, ob eine Sequenz vorhanden ist, kann die IF NOT EXISTS-Bedingung in PostgreSQL verwendet werden:

CREATE SEQUENCE IF NOT EXISTS 'name'

Siehe https://www.postgresql.org/docs/9.5/static/sql-createsequence.html

0
k_o_