3

MySQL でSETタイプを使用しようとしてPostgreSQLいますが、非常によく似た機能を備えているが要件を満たしていない配列しか見つかりませんでした。

PostgreSQL同様のデータ型がありますか?

4

6 に答える 6

2

次の回避策を使用できます。

1.ビット文字列

最大 N 要素のセットを単純に定義できますBIT(N)。データの取り込みと取得は少し面倒です。セット メンバーとしてビット マスクを使用する必要があります。しかし、ビット文字列は集合演算で真価を発揮します。交差は単に&、結合は|です。

このタイプは非常に効率的に格納されます。ビットごとに長さのオーバーヘッドが小さくなります。

また、長さが実際に制限されていないことも素晴らしいことです (ただし、事前に決定する必要があります)。

2.HSTORE _

HSTOREタイプは拡張機能ですが、インストールは非常に簡単です。単純に実行する

CREATE EXTENSION hstore

ほとんどのインストール (9.1+) で利用可能になります。噂によると、PostgreSQL 9.3HSTOREでは標準タイプになるということです。

これはセット型ではありませんが、Perl ハッシュや Python 辞書に似ています: key=>valueペアの任意のセットを保持します。

そのため、あまり効率的ではありません (確かに BIT 文字列効率的ではありません) が、セットに不可欠な機能を提供します:||結合のためですが、交差は少し扱いに​​くいです:

slice(a,akeys(b)) || slice(b,akeys(a))

HSTORE の詳細については、こちらをご覧ください。

于 2013-02-04T08:22:12.363 に答える
2

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.

于 2013-03-01T02:08:17.647 に答える
1

列挙型のデータ型をお探しですか?

PostgreSQL 9.1 列挙型

于 2013-02-03T16:29:08.097 に答える
0

少し前に、私は同様の拡張機能を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

于 2013-02-03T20:19:55.430 に答える
0

質問で参照されているページを読むと、SET は 1 つの列に最大 64 個の名前付きブール値を格納する方法のようです。PostgreSQL はこれを行う方法を提供していません。独立したブール列、または整数のいくつかのサイズを使用して、ビットを直接いじることができます。2 つの新しいテーブル (1 つは有効な名前用、もう 1 つは名前を詳細行に結合するため) を追加することは、特に他のデータを個々の値に関連付ける必要がある可能性がある場合に意味があります。

于 2013-02-03T17:38:10.543 に答える