我将数据列表存储在数据库中的字段中的序列化数组中(我使用的是PHP / MySQL)。
我想要一个查询,它将选择包含数组中这些项中特定项之一的所有记录。
这样的事情:
select * from table WHERE (an item in my array) = '$n'
希望这是有道理的。
非常感谢任何想法。
由于
答案 0 :(得分:24)
正如GWW在评论中所说,如果你需要以这种方式查询,你真的应该考虑将这些数据存储为除了大字符串之外的东西(这是你的序列化数组)。
如果那是不可能的(或者你只是懒惰),你可以使用序列化数组只是一个大字符串的事实,并找出一个LIKE子句来查找匹配的记录。 PHP序列化数据的方式很容易理解(提示:这些数字表示事物的长度)。
现在,如果你的序列化数组相当复杂,那么这将很快崩溃。但如果它是一个扁平阵列,你应该能够做到。
当然,你会使用LIKE'%...%',所以你不会得到任何指标的帮助,而且表现也会很差。
如果您需要在“内部”查询,那么人们建议您以某种标准化的方式存储数据的原因。
答案 1 :(得分:14)
所以你的意思是使用MySQL来搜索已经使用serialize命令序列化并存储在数据库字段中的PHP数组?我的第一反应是:OMG。我的第二反应是:为什么? 明智的要做的事情是:
我会选择第二个选项,但我不知道你的背景。
当然,如果你真的想要,你可以尝试使用SUBSTRING
或其他MySQL函数并尝试操作该字段,但我不明白你为什么要这样做。这很麻烦,这将是一个不必要的丑陋黑客。另一方面,这是一个谜题,这里的人往往喜欢谜题,所以如果你真的想然后发布你的领域的内容,我们可以给它一个镜头。
答案 2 :(得分:13)
如果您可以控制数据模型,那么在数据库中填充序列化数据将会长期困扰您。但是,通常一个不能控制数据模型,例如在使用某些开源内容管理系统时。 Drupal在dumpster列中粘贴 lot 序列化数据,代替正确的模型。例如,ubercart的所有订单都有一个“数据”列。贡献的模块需要将数据附加到主要订单实体,因此为了方便起见,他们将数据粘贴到序列化的blob上。作为第三方,我仍然需要一种方法来获取一些填充在那里的数据来回答一些问题。
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来凿掉无关紧要的数据,直到我将结果字符串雕刻成我想要的数据宝石。 然后我在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之后的所有内容,而外部的两个清理剩余部分。
这个复杂的hackery不是你想要的代码中运行不止一次的东西,更多的是一种从表中获取数据的工具,而不必求助于编写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的末尾)
答案 3 :(得分:4)
如何序列化您要搜索的值?
$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), '%');
答案 4 :(得分:3)
你可以这样做:
SELECT * FROM table_name WHERE some_field REGEXP '.*"item_key";s:[0-9]+:"item_value".*'
但无论如何你应该考虑将这些数据存储在一个单独的表中。
答案 5 :(得分:3)
嗯,我有同样的问题,显然它是小菜一碟,但也许它需要更多的测试。
只需使用IN语句,但将字段本身作为数组! 示例:
SELECT id, title, page FROM pages WHERE 2 IN (child_of)
〜其中&#39; 2&#39;是我在该领域内寻找的价值&#39; child_of&#39;这是一个序列化的数组。
这个序列化数组是必要的,因为我不能复制记录只是为了存储他们是孩子的id。
干杯
答案 6 :(得分:1)
上面有一个不错的REGEX答案,但是它假设使用key
和value
实现。如果您的序列化数组中只有values
,那么这对我有用:
仅值
SELECT * FROM table WHERE your_field_here REGEXP '.*;s:[0-9]+:"your_value_here".*'
键和值
SELECT * FROM table WHERE your_field_here REGEXP '.*"array_key_here";s:[0-9]+:"your_value_here".*'
答案 7 :(得分:0)
Select * from table where table_field like '%"enter_your_value"%'
答案 8 :(得分:0)
使用php序列化数据显然是很丑陋的,但是我得到了MySQL函数的这种线性组合,可以帮助解决这一问题:
select REPLACE(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(searchColumn, 'fieldNameToExtract', -1), ';', 2), ':', -1), '"', '') AS extractedFieldName
from tableName as t
having extractedFieldName = 'expressionFilter';
希望这会有所帮助!
答案 9 :(得分:0)
如果我在日志表中有attribute_dump字段,并且其中一行中的值具有
a:69:{s:9:"status_id";s:1:"2";s:2:"id";s:5:"10215"}
如果我要获取status_id等于2的所有行,则查询为
SELECT * FROM log WHERE attribute_dump REGEXP '.*"status_id";s:[0-9]+:"2".*'
答案 10 :(得分:0)
为方便使用方法:
column_field_name LIKE %VALUE_TO_BE_SEARCHED_FOR%
在MySQL查询中
答案 11 :(得分:-2)
您可能正在寻找SQL IN语句。
http://www.w3schools.com/sql/sql_in.asp
但是,你必须首先打破阵列。你不能只是将一个数组交给MySQL,并期望它知道如何处理它。为此,您可以尝试使用PHP的爆炸序列化它。
答案 12 :(得分:-2)
select * from postmeta where meta_key = 'your_key' and meta_value REGEXP ('6')
答案 13 :(得分:-2)
foreach( $result as $value ) {
$hour = unserialize( $value->meta_value );
if( $hour['date'] < $data['from'] ) {
$sum = $sum + $hour['hours'];
}
}
答案 14 :(得分:-3)
尝试切换到postgresql或mongodb。你的陈述伤害了第一个普通形式,也许纯粹的关系数据库不是你想要的。