2012-09-10 6 views

答えて

18

野次るが説明したように、あなたが整数に列挙型をキャストすることはできませんが、あなたは序表現を取得するために互換性のpg_enumシステム・カタログ表のPostgreSQL固有の、おそらくないバージョン・ツー・バージョンを使用することができます。

regress=# CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic'); 

regress=# select enumsortorder, enumlabel from pg_catalog.pg_enum 
regress-# WHERE enumtypid = 'happiness'::regtype ORDER BY enumsortorder; 
enumsortorder | enumlabel 
---------------+------------ 
      1 | happy 
      2 | very happy 
      3 | ecstatic 
(3 rows) 

これは簡単に見えますが、そうではありません。お守り:

regress=# ALTER TYPE happiness ADD VALUE 'sad' BEFORE 'happy'; 
regress=# ALTER TYPE happiness ADD VALUE 'miserable' BEFORE 'very happy'; 
regress=# SELECT * FROM pg_enum ; 
enumtypid | enumsortorder | enumlabel 
-----------+---------------+------------ 
    185300 |    1 | happy 
    185300 |    2 | very happy 
    185300 |    3 | ecstatic 
    185300 |    0 | sad 
    185300 |   1.5 | miserable 
(5 rows) 

このことからあなたはenumsortorderは順序が、固定されていない「距離」を提供していることがわかります。 enumから値を削除するサポートが追加されると、シーケンス内に「穴」が作成される可能性が高くなります。

列挙型のoidregtype)を取得するためにあなたが順序を取得するためにrow_number()ウィンドウ関数を使用する必要があります列挙位置、およびpg_typeofを取得します。同じラベルを持つ複数の列挙型があるときに正しい順序を返すようにするには、これが必要です。

この関数は、仕事をしていません:

CREATE OR REPLACE FUNCTION enum_to_position(anyenum) RETURNS integer AS $$ 
SELECT enumpos::integer FROM (
     SELECT row_number() OVER (order by enumsortorder) AS enumpos, 
       enumsortorder, 
       enumlabel 
     FROM pg_catalog.pg_enum 
     WHERE enumtypid = pg_typeof($1) 
    ) enum_ordering 
    WHERE enumlabel = ($1::text); 
$$ LANGUAGE 'SQL' STABLE STRICT; 

注:列挙型の追加(PGでのサポートが追加され、後にされている場合や、削除)の値が変化してしまうため

  • それはIMMUTABLEは、STABLEではありません注文に依存したインデックスの注文および中断、 so
  • これはインデックス式では使用できません。それがnullの入力のためにnullを返す必要がありますので、と
  • は、それはあなたが今integerに固有の列挙型のためCREATE CASTに、この機能を使用することができます

STRICTです。 integerにすべての列挙型の汎用キャストを作成することはできません。anyenum疑似型はキャストに使用できないためです。私はデモhappinessが整数にキャストすることができるようにしたい場合たとえば、私が書くでしょう:

CREATE CAST (happiness AS integer) WITH FUNCTION enum_to_position(anyenum); 

た後、私は正常に実行できます。これはおそらく非常識であることを

regress=# SELECT ('happy'::happiness)::integer; 
int4 
------ 
    2 
(1 row) 

注意をすること、サポートされていない、恐ろしいアイデアです。列挙値を追加するか(後でサポートされる場合)列挙値を削除するときに、序数値に変更されることをコードで認識しておく必要があります。

PostgreSQLは、このキャストに基づいて作成されたインデックス(機能が不変である場合のみ可能)は、列挙の定義を変更した場合(新しい値を追加しない限り)あなたが関数が不変であると言うとき、あなたはあなたです。それをしないでください。

3

整数に列挙することはできません。

数値に関連付けられた数字を抽出するためにcustom operatorを書くことができますが、それはその価値があると信じるのは難しいと思います。

このような情報が必要な場合は、テーブルを作成して列挙型を使用する代わりに、外部キー参照を設定していました。

11

これは、機能enum_range()を巧妙に悪用して行うことができます。

enum_range()関数の2番目の引数としてenum値を渡した場合、NULLが最初になると、enumがその点までにかかることができるすべての値を持つ配列が取得されます。次に、array_lengthで数えれば、列挙型を表す整数が得られます。

例を示します。これは私の列挙です:

content=# select enum_range(null::content_state); 
         enum_range       
-------------------------------------------------------------- 
{created,deleted,preview,draft,submitted,approved,published} 

そして、これは私は「ドラフト」値をint型を考え出すされています

content=# select array_length(enum_range(NULL, 'draft'::content_state), 1); 
array_length 
-------------- 
      4 

警告:列挙型から値を削除するには、あなたのint型は、他の値を指すようになります、ある時点で変更したい列挙型には使用しないでください。

0

はいできます。

enum型に整数値のみが含まれる場合、キャストは非常に簡単になります。 私のように列挙型を持っていると仮定します - 今、あなたは次のように別々のレコードとしてそれらを整数と表示するには、列挙型の値をキャスト使用することができます Create type monthenum as enum ('7', '8', '9', '10', '11', '12', '1', '2', '3', '4', '5', '6');

: -

select (unnest(enum_range(null::monthenum))::text)::integer as monthvalue 

希望、これはあなたが、アイデアを支援列挙型をテキストに変換してから、もう一度互換性のある型の列挙型に変換できるということです。また、forループを使用して値を1つずつ変換することもできます。