что вы спросили
~~
- это оператор, используемый для реализации SQL LIKE
. Для него нет коммутатора - нет оператора, который работает с переключенным левым и правым операндами.
Это то, что вам нужно для вашей попытки использовать ANY
конструкцию с шаблоном к слева . Связанный:
Вы можете создать оператор , и все довольно просто:
CREATE OR REPLACE FUNCTION reverse_like (text, text)
RETURNS boolean LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
'SELECT $2 LIKE $1';
CREATE OPERATOR <~~ (function = reverse_like, leftarg = text, rightarg = text);
Вдохновленный идеей Джеффа Джейнса здесь:
Тогда ваш запрос может иметь шаблон для слева оператора:
SELECT *
FROM mac_ip_addresses
WHERE '192.168.2%.255' <~~ ANY (ipaddress);
Простой, но значительно медленнее , чем EXISTS
выражение , продемонстрированное filiprem .
Опять же, любой запрос мучительно медленен для больших таблиц , поскольку ни один из них не может использовать index . Нормализованный дизайн БД с таблицей n: 1, содержащей по одному IP, позволил бы это. Это также заняло бы в несколько раз больше места на диске. Тем не менее, гораздо более чистая реализация ...
Пока вы застряли в своем текущем дизайне, есть еще способ: создать индекс GIN триграммы в текстовом представлении массива и добавить избыточный предикат «sargable» к запросу дополнительно. Смущенный? Вот рецепт:
Во-первых, индексы триграмм? Прочтите это, если вы не знакомы:
Ни приведенные от text[]
до text
, ни array_to_string()
не являются неизменными . Но нам это нужно для индекса выражения. Короче говоря, подделайте его с помощью неизменной функции-обертки:
CREATE OR REPLACE FUNCTION f_textarr2text(text[])
RETURNS text LANGUAGE sql IMMUTABLE AS $$SELECT array_to_string($1, ',')$$;
CREATE INDEX iparr_trigram_idx ON iparr
USING gin (f_textarr2text(iparr) gin_trgm_ops);
Связанный ответ с длинной историей (и почему это безопасно):
Тогда ваш запрос может быть:
SELECT *
FROM mac_ip_addresses
WHERE NOT ('192.168.9%.255' <~~ ANY (ipaddress))
AND f_textarr2text(ipaddress) LIKE '192.168.9%.255'; -- logically redundant
Добавленный предикат логически избыточен, но может задействовать всю мощь индекса триграммы.
Намного быстрее для больших столов. Еще немного быстрее, но:
SELECT *
FROM mac_ip_addresses
WHERE EXISTS (SELECT FROM unnest(ipaddress) ip WHERE ip LIKE '192.168.9%.255')
AND f_textarr2text(ipaddress) LIKE '192.168.9%.255';
Но теперь это незначительно.
дБ <> скрипка здесь
Я ответил на заданный вопрос, когда проявил интерес. Может представлять интерес для широкой публики. Скорее всего, не то, что вам нужно , хотя.
Что вам нужно нужно
Я хочу искать в ipAddress
с LIKE
. searchItem
содержит IP, который нужно искать в поле ipAddress
, поэтому я хочу искать в массиве с помощью LIKE
.
Это, вероятно, следует читать:
"Я хочу найти заданный IP-адрес (searchItem
) в массиве ipAddress
. Моя первая идея - использовать LIKE
..."
Ну, LIKE
для сопоставления с образцом. Чтобы найти полный IP-адрес в массиве, это неправильный инструмент. Второй запрос filiprem с операторами массива - это путь. Наверное, достаточно хорошо.
Было бы лучше использовать встроенный тип данных cidr
вместо text
. И тип данных ip4
дополнительного модуля ip4r был бы гораздо лучше. Все в сочетании со стандартными операторами массива, как показано.
Наконец, преобразование адресов IPv4 в integer
и использование его с дополнительным модулем inrarray должно быть звездным - что касается производительности.