web-dev-qa-db-ja.com

MySQLのようにPostgreSQL列挙型をクエリするにはどうすればよいですか?

MySQLの次のテーブルを使用します。

CREATE TABLE bob(foo ENUM('a','b','c'));

INSERT INTO bob (foo) VALUES ('a'),('b'),('c'),('a'),('a');

SELECT * FROM bob WHERE foo >= 2;
+------+
| foo  |
+------+
| b    |
| c    |
+------+

PostGresの次のテーブルを使用します。

CREATE TYPE stuff AS ENUM ('a', 'b', 'c');
INSERT INTO bob (foo) VALUES ('a'), ('b'), ('b'), ('c'), ('c');
SELECT * FROM bob WHERE foo > 2;
(HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.)

この問題を回避する方法はいくつかありますが、MySQLの機能を模倣するタイプを作成する方法はありますか?または、必要な機能を持つデータ型はありますか? (挿入時に文字列をチェックする機能だけでなく、集計に対してwhereケースを作成する機能)。

4
user3112092

MySQLが仕様に違反し、間抜けであるため、ENUMについて誤解があると思います。それらはMySQLとPostgreSQLの両方で異なりますが、PostgreSQLではより明らかに異なります。内部表現の詳細をシームレスにクエリしようとしています。私は実際にPostgreSQLがそれを阻止してくれてうれしいです。

代わりに ENUMサポート関数 を使用してください

CREATE TYPE stuff AS ENUM ('a', 'b', 'c');
SELECT * FROM enum_range('b'::stuff, NULL);

これは、「b」から列挙型の無制限のトップ(この場合は「c」)までのすべてを返します。

次に、テーブルを作成して値を挿入します。

CREATE TABLE bob ( foo stuff );
INSERT INTO bob (foo) VALUES ('a'),('b'),('c'),('a'),('a');

それを照会するには、次のようにします

SELECT *
FROM bob
WHERE foo = ANY(enum_range('b'::stuff, NULL));

あるいはもっと簡単に、アベリストがコメントで示唆したように。詳細はまだ抽象化されていることに注意してください。 bのソート順がわからない、

WHERE foo >= 'b'::stuff;
WHERE foo >= 'b';

列挙型はデフォルトで順序付けられます。 PostgreSQLでは、これらはint4として保存されます。 MySQLでは、これらはint2またはint1として格納されます。ただし、それらの実装はユーザーに公開しないでください。

上記のクエリで、値を追加した後にデータベースから再読み込みすると、列挙型が並べ替えられる可能性があると考えてください。次に、2に特定の値を想定しているため、クエリが失敗します。

も参照してください、

4
Evan Carroll