30

ストアドプロシージャ内で、シーケンスがすでに存在するかどうかをテストしようとしています。

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

私は運がなくて上記のスニペットのいくつかのバリエーションを試しました。私はそのトピックについて何も見つけられないように見えるので、私はグーグルに間違った用語を与えているに違いありません。どんな助けでも大歓迎です!

4

6 に答える 6

27

pg_classテーブルをクエリして、relnameが存在するかどうかを確認できるはずです。

IF EXISTS (SELECT 0 FROM pg_class where relname = '<my sequence name here>' )
THEN
  --stuff here
END IF;
于 2012-08-10T17:06:31.867 に答える
19

@rfuscaからの回答は、名前がシーケンスに対してのみ有効であることが確実な場合(つまり、通常のテーブル、インデックス、ビュー、複合型、TOASTテーブル、または外部テーブル)、および複数のスキーマについて心配する必要はありません。言い換えれば、それはほとんどの一般的なケースで機能しますが、完全に厳密ではありません。

その名前のシーケンスが特定のスキーマに存在するかどうかをテストする場合、これは機能するはずです。

-- 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;
于 2012-08-10T18:36:05.570 に答える
15

更新:to_regclass()Postgres 9.4では、存在のテストが簡単になりました。

SELECT to_regclass('schema_name.table_name');

しかし、詳細を読んでください:

完全な機能

シーケンスだけでなく、名前と競合するテーブルのようなオブジェクトをチェックする必要があります。

この関数は、名前が使用可能な場合は新しいシーケンスを作成し、それ以外の場合はそれぞれ意味のあるNOTICE//を発行しWARNINGます。EXCEPTION

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)';

電話:

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

または:

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

説明

  • コードの最後にある関数へのコメントも読んでください。

  • Postgres9.1以降で動作します。古いバージョンの場合は、置き換える必要があるだけですformat()。これは、SQLインジェクションを防ぎます。詳細:

  • 2つの別個のパラメーターにより、現在のスキーマに依存しない任意のスキーマのシーケンスが可能になり、そのジョブを実行することsearch_pathもできます。スキーマ修飾名で失敗する-あいまいになります。quote_ident()quote_ident()

  • スキーマパラメータにはデフォルト値があるため、呼び出しから省略できます。スキーマが指定されていない場合、関数はデフォルトで。になりcurrent_schemaます。ドキュメントごと:

    current_schema検索パスの最初にあるスキーマの名前を返します(検索パスが空の場合はnull値)。これは、ターゲットスキーマを指定せずに作成されたテーブルまたはその他の名前付きオブジェクトに使用されるスキーマです。

  • pgclass.relkindマニュアルのタイプのリスト。

  • PostgreSQLエラーコード

于 2012-08-12T03:54:57.747 に答える
9

情報スキーマを使ってみませんか:

SELECT COUNT(*) 
FROM information_schema.sequences 
WHERE sequence_schema=? AND sequence_name=?
于 2016-06-15T09:06:05.393 に答える
1
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';

結果:

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

このクエリは、スキーマ内のシーケンスの存在を確認できます。

于 2015-02-13T23:45:03.793 に答える
1

シーケンスの存在をチェックする必要がある理由が実際の意図についてはわかりません。シーケンスを作成する前にシーケンスが存在するかどうかを確認することが目的の場合はIF NOT EXISTS、PostgreSQLの条件を使用できます。

CREATE SEQUENCE IF NOT EXISTS 'name'

https://www.postgresql.org/docs/9.5/static/sql-createsequence.htmlを参照してください

于 2018-06-11T14:43:59.443 に答える