mysql select query в сериализованном массиве

Я сохраняю список элементов в сериализованном массиве в поле в моей базе данных (я использую PHP / MySQL).

Я хочу иметь запрос, который будет выбирать все записи, содержащие определенный один из этих элементов, который находится в массиве.

Что-то вроде этого:

select * from table WHERE (an item in my array) = '$n' 

Надеюсь, это имеет смысл.

Любые идеи очень приветствуются.

благодаря

Итак, вы хотите использовать MySQL для поиска в массиве PHP, который был сериализован с помощью команды serialize и хранится в поле базы данных? Моя первая реакция была бы: OMG. Моя вторая реакция была бы: почему? Разумная вещь – либо:

  1. Извлеките массив в PHP, несериализуйте его и выполните поиск в нем
  2. Забудьте о хранении данных в MySQL как сериализованных и сохраните его как обычную таблицу и проиндексируйте ее для быстрого поиска

Я бы выбрал второй вариант, но я не знаю вашего контекста.

Конечно, если вы действительно этого захотите, вы можете попробовать что-то с SUBSTRING или другой функцией MySQL и попытаться манипулировать этим полем, но я не понимаю, зачем вам это нужно. Это громоздко, и это было бы ненужным уродливым взломом. С другой стороны, это головоломка, и люди здесь любят головоломки, поэтому, если вы действительно захотите опубликовать содержимое своего поля, и мы сможем сделать это.

Как говорит GWW в комментариях, если вам нужно запрашивать такие вещи, вам действительно стоит подумать о том, чтобы хранить эти данные как нечто отличное от большой-ole-строки (что и является вашим сериализованным массивом).

Если это невозможно (или вы просто ленивы), вы можете использовать тот факт, что сериализованный массив является просто большой строкой и вычисляет предложение LIKE, чтобы найти соответствующие записи. То, как PHP сериализует данные, довольно легко понять (подсказка: эти цифры указывают длину вещей).

Теперь, если ваш сериализованный массив довольно сложный, это быстро сломается. Но если это плоский массив, вы должны это сделать.

Конечно, вы будете использовать LIKE '% …%', поэтому вы не получите никакой помощи от каких-либо указаний, и производительность будет очень плохой.

Именно поэтому люди предлагают вам хранить эти данные в некотором нормализованном виде, если вам нужно запросить «внутри».

Если у вас есть контроль над моделью данных, набивка сериализованных данных в базе данных будет укусить вас в конечном счете почти всегда. Однако, как правило, у одного нет контроля над моделью данных, например, при работе с определенными системами управления контентом с открытым исходным кодом. Drupal хранит много сериализованных данных в столбцах корзины вместо правильной модели. Например, ubercart имеет столбец «данные» для всех своих заказов. Добавленные модули должны прикреплять данные к основному объекту заказа, поэтому из удобства они привязывают его к сериализованному блобу. Как третье лицо, мне все же нужен способ получить некоторые данные, заполненные там, чтобы ответить на некоторые вопросы.

 a:4:{s:7:"cc_data";s:112:"6"CrIPY2IsMS1?blpMkwRj[XwCosb]gl<Dw_L(,Tq[xE)~(!$C"9Wn]bKYlAnS{[Kv[&Cq$xN-Jkr1qq<z](td]ve+{Xi!G0x:.O-"=yy*2KP0@z";s:7:"cc_txns";a:1:{s:10:"references";a:1:{i:0;a:2:{s:4:"card";s:4:"3092";s:7:"created";i:1296325512;}}}s:13:"recurring_fee";b:1;s:12:"old_order_id";s:2:"25";} 

видите, что «old_order_id»? вот ключ, который мне нужен, чтобы узнать, откуда пришел этот повторяющийся заказ, но поскольку не каждый использует модуль повторяющихся заказов, не существует надлежащего места для его хранения в базе данных, поэтому разработчик модуля решил заполнить его в этой таблице мусорных контейнеров.

Мое решение состоит в том, чтобы использовать несколько целевых SUBSTRING_INDEX для того, чтобы вытолкнуть незначительные данные, пока я не обработал результирующую строку в gemstone моих желаний. Затем я придерживаюсь предложения HAVING, чтобы найти все, что соответствует, например:

 SELECT uo.*, SUBSTRING_INDEX( SUBSTRING_INDEX( SUBSTRING_INDEX( uo.data, 'old_order_id' , -1 ), '";}', 1), '"',-1) AS `old order id` FROM `uc_orders AS `uo` HAVING `old order id` = 25 

Самый внутренний SUBSTRING_INDEX дает мне все прошлое old_order_id, а внешние два очищают остаток.

Этот сложный хакер – это не то, что вы хотите в коде, который работает более одного раза, а больше инструмент для вывода данных из таблицы без необходимости прибегать к написанию сценария php.

Обратите внимание, что это можно упростить до простого

 SELECT uo.*, SUBSTRING_INDEX( SUBSTRING_INDEX( uo.data, '";}' , 1 ), '"',-1) AS `old order id` FROM `uc_orders` AS `uo` HAVING `old order id` = 25 

но это будет работать только в этом конкретном случае (значение, которое я хочу, находится в конце данных blob)

Как насчет сериализации значения, которое вы ищете?

 $sql = sprintf("select * from tbl WHERE serialized_col like '%%%s%%'", serialize($n)); 

или

 $sql = sprintf("select * from tbl WHERE serialized_col like '%s%s%s'", '%', serialize($n), '%'); 

Вы можете сделать это следующим образом:

 SELECT * FROM table_name WHERE some_field REGEXP '.*"item_key";s:[0-9]+:"item_value".*' 

Но в любом случае вам следует рассмотреть возможность хранения этих данных в отдельной таблице.

Ну, у меня была такая же проблема, и, видимо, это кусок пирога, но, возможно, ей нужно больше тестов.

Просто используйте инструкцию IN, но поместите поле как массив! Пример:

 SELECT id, title, page FROM pages WHERE 2 IN (child_of) 

~ где '2' – это значение, которое я ищу внутри поля 'child_of', который является сериализованным массивом.

Этот сериализованный массив был необходим, потому что я не могу дублировать записи только для хранения того, с каким они были детьми.

ура

Возможно, вы ищете инструкцию SQL IN.

http://www.w3schools.com/sql/sql_in.asp

Тем не менее, вам придется сначала разбить ваш массив. Вы не можете просто передать массив в MySQL и ожидать, что он будет знать, что с ним делать. Для этого вы можете попробовать сериализовать его с помощью взрыва PHP.

http://php.net/manual/en/function.explode.php

 Select * from table where table_field like '%"enter_your_value"%' 
 select * from postmeta where meta_key = 'your_key' and meta_value REGEXP ('6') 

Попробуйте переключиться на postgresql или mongodb. Ваше заявление повреждает 1-ю нормальную форму, возможно, чистые реляционные базы данных – это не то, что вы хотите.