Vérifier si la séquence existe dans Postgres (plpgsql)

j'essaie de tester, dans une procédure stockée, si une séquence existe déjà.

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

j'ai essayé plusieurs variantes de l'extrait ci-dessus, mais sans succès. Je dois donner à Google les mauvais termes parce que je ne semble pas trouver quoi que ce soit sur le sujet. Toute aide est appréciée!

20
demandé sur Erwin Brandstetter 2012-08-10 20:40:25

6 réponses

vous devriez pouvoir interroger la table pg_class pour voir si le relname existe.

IF EXISTS (SELECT 0 FROM pg_class where relname = '<my sequence name here>' )
THEN
  --stuff here
END IF;
19
répondu rfusca 2012-08-10 17:06:31

la réponse de @rfusca fonctionne si vous êtes sûr que le nom ne pourrait être valide que pour une séquence (c.-à-d., Vous êtes sûr qu'il ne serait pas utilisé pour une table ordinaire, index, vue, type composite, table TOAST, ou table étrangère), et vous n'êtes pas préoccupé par plusieurs schémas. En d'autres termes, cela fonctionne pour la plupart des cas courants, mais ce n'est pas tout à fait rigoureux.

si vous voulez vérifier si une" séquence de ce nom existe dans une schéma , cela devrait fonctionner:

-- 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;
17
répondu kgrittn 2014-01-22 14:51:09

mise à jour: simplement tester l'existence est devenu plus simple avec to_regclass() en Postgres 9.4 :

SELECT to_regclass('schema_name.table_name');

mais lisez les détails:

Complète de la fonction

, Vous devez vérifier pour tout table-comme l'objet qui serait en conflit avec le nom, pas seulement des séquences.

cette fonction crée une nouvelle séquence si le nom est disponible et émet une NOTICE / WARNING / EXCEPTION dans les autres cas:

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.
 _seq    .. sequence name 
 _schema .. schema name (optional; default is CURRENT_SCHEMA)';

appel:

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

ou:

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

expliquer

  • aussi lire le commentaire à la fonction à la fin du code.

  • Travaille dans Postgres 9.1+ . Pour les versions plus anciennes, vous avez seulement besoin de remplacer format() - qui défend contre L'injection SQL. Details:

  • deux des paramètres séparés permettent des séquences dans n'importe quel schéma indépendant de l'actuel search_path et permettent également à quote_ident() de faire son travail. quote_ident() échoue avec des noms schema-qualifiés - serait ambigu.

  • il y a une valeur par défaut pour le paramètre schema, donc vous pouvez l'omettre de l'appel. Si aucun schéma n'est donné, la fonction est par défaut current_schema . par documentation:

    current_schema renvoie le nom du schéma qui est le premier dans le chemin de recherche (ou une valeur null si le chemin de recherche est vide). C'est le le schéma qui sera utilisé pour toutes les tables ou autres objets nommés que sont créés sans spécifier de schéma cible.

  • liste des types pour pgclass.relkind dans le manuel .

  • Codes d'erreur PostgreSQL .

12
répondu Erwin Brandstetter 2017-05-23 10:31:28

Que Diriez-vous d'utiliser le schéma d'information:

SELECT COUNT(*) 
FROM information_schema.sequences 
WHERE sequence_schema=? AND sequence_name=?
6
répondu Dave Kok 2017-03-31 14:01:24
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';

résultat:

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

Cette requête peut vérifier l'existence d'une séquence à l'intérieur d'un schéma.

1
répondu xingang 2015-02-25 01:29:06

Je ne suis pas sûr de l'intention réelle pourquoi la présence de la séquence doit être vérifiée. Une alternative si le but est de vérifier si une séquence existe avant de la créer, la condition IF NOT EXISTS dans PostgreSQL peut être utilisée:

CREATE SEQUENCE IF NOT EXISTS 'name'

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

0
répondu k_o_ 2018-06-23 19:13:21