Mysql SET-Äquivalent in postgres? Evtl. Array?

Hallo, ich habe meine Mysql-Datenbank auf eine Postgres-Datenbank umgestellt. Allerdings gibts dabei ein Problem, es werden in Postgres keine Spalten mit dem Typ SET unterstützt. Daher meine Frage, gibt es einen äquivalenten Typ in postgres? Definition von SET lt. der offiziellen Mysql-Doku: A SET value must be the empty string or a value consisting only of the values listed in the column definition separated by commas. Ich habe mir dann gedacht, der PostgreTyp Array (mit enum-werten) ist eig. wesentlich besser, als der Mysql SET-Typ, allerdings darf ein Array in Postgres ja auch einen leeren string enthalten, was ich nicht will. ich will, dass in dieser Spalte mindestens eines der vorhandenen enum-werte ausgewählt werden kann, und maximal alle. Mein sql-query sieht in etwa so aus: CREATE TYPE terrain_types_enum AS ENUM(‘lowland’,‘highland’,‘mountains’,‘floodplain’,‘coast’); CREATE TABLE test ( terrain_types terrain_types_enum[] NOT NULL, ); Allerdings ist es dabei wie schon gesagt möglich, auch ein INSERT INTO test (terrain_types) VALUES (’{NULL}’); zu machen.

Klingt nach einem CHECK-Constraint. Du kannst damit Prüfungen definieren, die erfüllt sein müssen. Ich denke mal, damit könntest Du zum Ziel kommen …


Andreas

Was spricht gegen ENUM?

Dies: “value consisting only of the values listed in the column definition separated by commas”.

Andreas

Hallo, danke an akretschmer, für den Hinweis, das hört sich echt nach einer lösung an.

@ads
Also ich möchte mehrere werte in eine spalte reinbringen.
Gut, ich gebe es zu, es ist nicht ganz sauber, man sollte das schon relationell über eine weitere tabelle lösen, auf die man dann mit den ids referenziert, aber der aufwand und ein join sind mir dann doch etwas zu aufwendig.
also die lösung muss nicht unbedingt in den so sein, dass ich die einträge durch kommas getrennt haben will, aber wie gesagt es sollte möglich sein, beliebig viele werte aus dem enum (jedoch mindestens einen) auszuwählen.
Ich finde das pg-array in dieser hinsicht eh viel genialer, weil es dich ja nicht sosehr einschränkt wie das mysql set, (hier ist es nicht möglich, dass der string beistriche enthält und außerdem dürfen nur maximal 64 annehmbare werte sein.)


Habe mir jetzt mal sowas geschrieben:
CREATE TABLE test ( terrain_types metsit_terrain_types_enum[] NOT NULL CHECK( terrain_types != ‘{}’ AND terrain_types != ‘{NULL}’ AND NULL != ANY (terrain_types) ) );

Allerdings funktioniert mit dieser tabelle auch ein:
INSERT INTO test (terrain_types) VALUES (’{lowland,NULL}’);

Die folgenden funktionieren jetzt nicht mehr (was auch so gewollt ist):
INSERT INTO test (terrain_types) VALUES (’{NULL}’);
INSERT INTO test (terrain_types) VALUES (’{}’);

Weiß jemand, warum das nicht funktioniert, weil scheinbar ignoriert er das NULL != ANY (terrain_types).

Ich bin eher kein Freund von Arrays und würde eher zu einer weiteren Tabelle raten, aber egal.

So aus dem Handgelenk würde ich sagen, daß eine Prüfung NULL != ANY () so nicht geht, aber ich kann mich da irren …


Andreas

@andreas,
ja, es ist vielleicht nicht ganz so optimal, mit dem array in einer datenbank, wenn man relationale tabellen verwenden kann, aber ich muss im grunde nur eine datenbank von postgres nach mysql portieren. und ich darf nicht zu viel darüber nachdenken, ob ein array-feld sinnvoll ist, oder nicht.
ok, hat jemand eine idee, wie ich eine überprüfung der array-elemente auf NOT NULL in dem CHECK unterbringen kann?

Nun, du könntest eine Funktion schreiben. Grob gesaht also sowas wie hier:

test=# create type my_type as enum ('foo','bar','batz');
CREATE TYPE
Zeit: 0,408 ms
test=*# create or replace function my_check() returns bool as $$begin return true; end;$$ language plpgsql;
CREATE FUNCTION
Zeit: 0,504 ms
test=*# create table my_foo ( id serial, my_enum my_type[] check ((my_check())));
NOTICE:  CREATE TABLE will create implicit sequence "my_foo_id_seq" for serial column "my_foo.id"
CREATE TABLE
Zeit: 19,152 ms

Der Funktion halt als Parameter Dein Array übergeben und in der Funktion prüfen, ob es ein NULL-Element enthält.


Andreas