MySQL
でSETタイプを使用しようとしてPostgreSQL
いますが、非常によく似た機能を備えているが要件を満たしていない配列しか見つかりませんでした。
PostgreSQL
同様のデータ型がありますか?
MySQL
でSETタイプを使用しようとしてPostgreSQL
いますが、非常によく似た機能を備えているが要件を満たしていない配列しか見つかりませんでした。
PostgreSQL
同様のデータ型がありますか?
次の回避策を使用できます。
最大 N 要素のセットを単純に定義できますBIT(N)
。データの取り込みと取得は少し面倒です。セット メンバーとしてビット マスクを使用する必要があります。しかし、ビット文字列は集合演算で真価を発揮します。交差は単に&
、結合は|
です。
このタイプは非常に効率的に格納されます。ビットごとに長さのオーバーヘッドが小さくなります。
また、長さが実際に制限されていないことも素晴らしいことです (ただし、事前に決定する必要があります)。
HSTORE
タイプは拡張機能ですが、インストールは非常に簡単です。単純に実行する
CREATE EXTENSION hstore
ほとんどのインストール (9.1+) で利用可能になります。噂によると、PostgreSQL 9.3HSTORE
では標準タイプになるということです。
これはセット型ではありませんが、Perl ハッシュや Python 辞書に似ています: key
=>value
ペアの任意のセットを保持します。
そのため、あまり効率的ではありません (確かに BIT 文字列効率的ではありません) が、セットに不可欠な機能を提供します:||
結合のためですが、交差は少し扱いにくいです:
slice(a,akeys(b)) || slice(b,akeys(a))
HSTORE の詳細については、こちらをご覧ください。
Building on a_horse_with_no_name's answer above, I would suggest something just a little more complex:
CREATE FUNCTION set_check(in_value anyarray, in_check anyarray)
RETURNS BOOL LANGUAGE SQL IMMUTABLE AS
$$
WITH basic_check AS (
select bool_and(v = any($2)) as condition, count(*) as ct
FROM unnest($1) v
GROUP BY v
), length_check AS (
SELECT count(*) = 0 as test FROM unnest($1)
)
SELECT bool_and(condition AND ct = 1)
FROM basic_check
UNION
SELECT test from length_check where test;
$$;
Then you should be able to do something like:
CREATE TABLE set_test (
my_set text[] CHECK (set_check(my_set, array['one'::text,'two']))
);
This works:
postgres=# insert into set_test values ('{}');
INSERT 0 1
postgres=# insert into set_test values ('{one}');
INSERT 0 1
postgres=# insert into set_test values ('{one,two}');
INSERT 0 1
postgres=# insert into set_test values ('{one,three}');
ERROR: new row for relation "set_test" violates check constraint "set_test_my_set_check"
postgres=# insert into set_test values ('{one,one}');
ERROR: new row for relation "set_test" violates check constraint "set_test_my_set_check"
Note this assumes that for your set, every value must be unique (we are talking sets here). The function should perform very well and should meet your needs. However this has the advantage of handling any size sets.
Storage-wise it is completely different from MySQL's implementation. It will take up more space on disk but should handle sets with as many members as you like, provided that you aren't running up against storage limits.... So this should have a superset of functionality in comparison to MySQL's implementation. One significant difference though is that this does not collapse the array into distinct values. It just prohibits them. If you need that too, look at a trigger.
This solution also leaves the ordinality of input data intact so '{one,two}' is distinct from '{two,one}' so if you need to ensure that behavior has changed, you may want to look into exclusion constraints on PostgreSQL 9.2.
列挙型のデータ型をお探しですか?
少し前に、私は同様の拡張機能を1つ書きました
https://github.com/okbob/Enumset
しかし、それは完全ではありません
より完全で mysql に近いのは、pltoolkit の機能です。
http://okbob.blogspot.cz/2010/12/bitmapset-for-plpgsql.html http://pgfoundry.org/frs/download.php/3203/pltoolbox-1.0.2.tar.gz http:// postgres.cz/wiki/PL_toolbox_%28en%29
関数 find_in_set は配列を介してエミュレートできます
http://okbob.blogspot.cz/2009/08/mysql-functions-for-postgresql.html
質問で参照されているページを読むと、SET は 1 つの列に最大 64 個の名前付きブール値を格納する方法のようです。PostgreSQL はこれを行う方法を提供していません。独立したブール列、または整数のいくつかのサイズを使用して、ビットを直接いじることができます。2 つの新しいテーブル (1 つは有効な名前用、もう 1 つは名前を詳細行に結合するため) を追加することは、特に他のデータを個々の値に関連付ける必要がある可能性がある場合に意味があります。