Solusi
Kemungkinan besar, solusi adalah untuk memenuhi syarat skema operator:
SELECT *
FROM test
WHERE tagged OPERATOR([email protected]>) '{11}'::int2[]
ORDER BY id
LIMIT 100;
Mengapa?
Ini masalah resolusi operator (dikombinasikan dengan resolusi jenis dan konteks pemeran).
Di Postgres standar, hanya ada satu kandidat operator anyarray @> anyarray
, itu yang Anda inginkan.
Penyiapan Anda akan berfungsi dengan baik jika Anda tidak memasang intarray modul tambahan (asumsi saya), yang menyediakan operator lain untuk integer[] @> integer[]
.
Oleh karena itu, solusi lain adalah menggunakan integer[]
sebagai gantinya dan memiliki indeks GIN dengan gin__int_ops
kelas operator. Atau coba (default untuk intarray) gist__int_ops
indeks. Mungkin lebih cepat, tetapi keduanya tidak mengizinkan nilai NULL.
Atau Anda dapat mengganti nama intarray
operator @>
untuk disambiguasi. (Saya tidak akan melakukannya. Masalah peningkatan dan portabilitas terjadi.)
Untuk ekspresi yang melibatkan setidaknya satu operan bertipe integer[]
, Postgres tahu operator mana yang harus dipilih:operator intarray. Tapi kemudian indeks tidak berlaku , karena operator intarray hanya beroperasi pada integer
(int4
) bukan int2
. Dan indeks sangat terikat dengan operator:
- Dapatkah PostgreSQL mengindeks kolom array?
- Perilaku PostgreSQL dengan adanya dua jenis indeks yang berbeda pada kolom yang sama
Tapi untuk int2[] @> int2[]
, Postgres tidak dapat menentukan operator terbaik. Keduanya tampak sama-sama berlaku. Karena operator default disediakan di pg_catalog
skema dan operator intarray disediakan di public
schema (secara default - atau di mana pun Anda memasang ekstensi), Anda dapat membantu memecahkan teka-teki dengan membuat operator memenuhi syarat skema dengan OPERATOR()
membangun. Terkait:
- Bandingkan array untuk kesetaraan, abaikan urutan elemen
Pesan kesalahan yang Anda dapatkan agak menyesatkan. Tetapi jika Anda perhatikan lebih dekat, ada HINT
baris menambahkan petunjuk mana (tada!) ke arah yang benar:
ERROR: operator is not unique: smallint[] @> smallint[] LINE 1: SELECT NULL::int2[] @> NULL::int2[] ^ HINT: Could not choose a best candidate operator. You might need to add explicit type casts.
Anda dapat menyelidiki kandidat operator yang ada untuk @>
dengan:
SELECT o.oid, *, oprleft::regtype, oprright::regtype, n.nspname
FROM pg_operator o
JOIN pg_namespace n ON n.oid = o.oprnamespace
WHERE oprname = '@>';
Solusi alternatif lain adalah untuk sementara(!) menyetel search_path yang berbeda, jadi hanya operator yang diinginkan yang ditemukan. Dalam transaksi yang sama:
SET LOCAL search_path = pg_catalog;
SELECT ...
Namun kemudian Anda harus membuat skema-kualifikasi semua tabel dalam kueri.
Tentang konteks pemeran:
- Buat rangkaian tanggal - menggunakan jenis tanggal sebagai masukan
Anda bisa ubah castcontext
dari int2
-> int4
. Tapi saya sangat menyarankan untuk tidak melakukannya. Terlalu banyak kemungkinan efek samping:
- Apakah ada cara untuk mentransmisikan tipe data postgresql 9.3 sehingga hanya dapat mempengaruhi satu sisi