我将数据列表存储在数据库中的字段中的序列化数组中(我使用的是PHP/MySQL).
我想要一个查询,它将选择包含数组中这些项中特定项之一的所有记录.
像这样的东西:
select * from table WHERE (an item in my array) = '$n'
Run Code Online (Sandbox Code Playgroud)
希望这是有道理的.
任何想法将不胜感激.
谢谢
tim*_*dev 24
正如GWW在评论中所说,如果你需要以这种方式查询,你真的应该考虑将这些数据存储为除了大字符串之外的东西(这是你的序列化数组).
如果那是不可能的(或者你只是懒惰),你可以使用序列化数组只是一个大字符串的事实,并找出一个LIKE子句来查找匹配的记录.PHP序列化数据的方式很容易理解(提示:这些数字表示事物的长度).
现在,如果您的序列化数组相当复杂,这将很快崩溃.但如果它是一个扁平阵列,你应该能够做到.
当然,你会使用LIKE'%...%',所以你不会得到任何指标的帮助,而且表现会很差.
这就是为什么人们建议你以一些标准化的方式存储数据,如果你需要查询"内部"它.
tho*_*ulb 14
所以你的意思是使用MySQL来搜索已经使用serialize命令序列化并存储在数据库字段中的PHP数组?我的第一反应是:OMG.我的第二反应是:为什么?在理智的事情可以是:
我会选择第二种选择,但我不知道你的背景.
当然,如果你真的想要,你可以尝试使用SUBSTRING其他MySQL功能,并尝试操作该字段,但我不明白你为什么要这样做.这很麻烦,这将是一个不必要的丑陋黑客.另一方面,这是一个谜题,这里的人往往喜欢谜题,所以如果你真的想发布你的领域的内容,我们可以给它一个镜头.
Mix*_*gic 13
如果您可以控制数据模型,那么在数据库中填充序列化数据将会长期困扰您.但是,通常人们无法控制数据模型,例如在使用某些开源内容管理系统时.Drupal 在垃圾箱列中粘贴了大量序列化数据,代替了正确的模型.例如,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";}
Run Code Online (Sandbox Code Playgroud)
看到'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
Run Code Online (Sandbox Code Playgroud)
最里面的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
Run Code Online (Sandbox Code Playgroud)
但这只适用于这种特定情况(我想要的值是在数据blob的末尾)
小智 9
你可以这样做:
SELECT * FROM table_name WHERE some_field REGEXP '.*"item_key";s:[0-9]+:"item_value".*'
Run Code Online (Sandbox Code Playgroud)
但无论如何,您应该考虑将该数据存储在单独的表中。
小智 5
使用 php 序列化数据显然是相当难看的,但我有一个 MySQL 函数的线性组合,可以帮助解决这个问题:
select REPLACE(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(searchColumn, 'fieldNameToExtract', -1), ';', 2), ':', -1), '"', '') AS extractedFieldName
from tableName as t
having extractedFieldName = 'expressionFilter';
Run Code Online (Sandbox Code Playgroud)
希望这能有所帮助!