Вы можете использовать LIKE. Вы не хотите соответствовать частичным значениям, поэтому вам придется включать запятые в свой поиск. Это также означает, что вам нужно будет предоставить дополнительную запятую для поиска значений в начале или конце текста:
select
*
from
YourTable
where
',' || CommaSeparatedValueColumn || ',' LIKE '%,SearchValue,%'
Но этот запрос будет медленным, как и все запросы с использованием LIKE, особенно с ведущим шаблоном.
И всегда есть риск. Если вокруг значений есть пробелы или значения могут содержать запятые, в этом случае они окружены кавычками (например, в файлах csv), этот запрос не будет работать, и вам придется добавить еще больше логики, замедляя ваш запрос еще больше.
Лучшим решением было бы добавить дочернюю таблицу для этих категорий. Или, скорее, даже отдельная таблица для каталогов и таблица, которая пересекает их с помощью YourTable.
Пока список с разделителями-запятыми составляет 512 символов или меньше, вы также можете использовать регулярное выражение в этом экземпляре (функции регулярного выражения Oracle, например REGEXP_LIKE()
, ограничены 512 символами):
SELECT id, categories
FROM mytable
WHERE REGEXP_LIKE('c2', '^(' || REPLACE(categories, ',', '|') || ')$', 'i');
В вышеизложенном я заменяю запятые оператором чередования регулярных выражений |
. Если ваш список ограниченных значений уже |
-пределен, тем лучше.
Для будущих поисковиков не забудьте путь регулярного выражения:
with tbl as (
select 1 ID, 'c1' CATEGORIES from dual
union
select 2 ID, 'c2,c3' CATEGORIES from dual
union
select 3 ID, 'c3,c2' CATEGORIES from dual
union
select 4 ID, 'c3' CATEGORIES from dual
union
select 5 ID, 'c4,c8,c5,c100' CATEGORIES from dual
)
select *
from tbl
where regexp_like(CATEGORIES, '(^|\W)c3(\W|$)');
ID CATEGORIES
---------- -------------
2 c2,c3
3 c3,c2
4 c3
Это соответствует границе слова, поэтому даже если запятая сопровождалась пробелом, оно все равно будет работать , Если вы хотите быть более строгим и соответствовать только там, где запятая разделяет значения, замените «\ W» запятой. Во всяком случае, прочитайте регулярное выражение как: соответствие группе либо начала строки, либо границы слова, за которой следует целевое значение поиска, за которым следует группа либо границы слова, либо конца строки.
Вы можете написать функцию таблицы PIPELINED, которая возвращает 1 столбец столбца. Каждая строка представляет собой значение из строки, разделенной запятыми. Используйте это как pop
строку из списка, а put
- как строку в таблице:
PIPE ROW(ltrim(rtrim(substr(l_list, 1, l_idx - 1),' '),' '));
Использование:
SELECT * FROM MyTable
WHERE 'c2' IN TABLE(Util_Pkg.split_string(categories));
Подробнее см. Здесь : Oracle docs
Да и Нет ...
«Да»:
Нормализовать данные (настоятельно рекомендуется) - т.е. разбить столбец категории, чтобы каждая категория была отдельной. .. тогда вы можете просто запросить его в обычном faschion ...
«Нет»: пока вы держите эту «псевдоструктуру», будет несколько проблем (производительность и другие), и вы будете должен сделать что-то похожее на:
SELECT * FROM MyTable WHERE categories LIKE 'c2,%' OR categories = 'c2' OR categories LIKE '%,c2,%' OR categories LIKE '%,c2'
ЕСЛИ вы абсолютно должны определить функцию, которая называется FIND_IN_SET, как показано ниже:
CREATE OR REPLACE Function FIND_IN_SET
( vSET IN varchar2, vToFind IN VARCHAR2 )
RETURN number
IS
rRESULT number;
BEGIN
rRESULT := -1;
SELECT COUNT(*) INTO rRESULT FROM DUAL WHERE vSET LIKE ( vToFine || ',%' ) OR vSET = vToFind OR vSET LIKE ('%,' || vToFind || ',%') OR vSET LIKE ('%,' || vToFind);
RETURN rRESULT;
END;
Затем вы можете использовать эту функцию например:
SELECT * FROM MyTable WHERE FIND_IN_SET (categories, 'c2' ) > 0;