序列化数组中的 mysql 选择查询
我正在将序列化数组中的项目列表存储在数据库的字段中(我使用的是PHP / MySQL)。
我想要一个查询,该查询将选择包含数组中特定项之一的所有记录。
像这样:
select * from table WHERE (an item in my array) = '$n'
希望这是有道理的。
任何想法将不胜感激。
谢谢
我正在将序列化数组中的项目列表存储在数据库的字段中(我使用的是PHP / MySQL)。
我想要一个查询,该查询将选择包含数组中特定项之一的所有记录。
像这样:
select * from table WHERE (an item in my array) = '$n'
希望这是有道理的。
任何想法将不胜感激。
谢谢
正如GWW在注释中所说,如果您需要以这种方式查询事物,那么您确实应该考虑将此数据存储为大字符串以外的其他内容(这就是您的序列化数组)。
如果这是不可能的(或者你只是懒惰),你可以使用序列化数组只是一个大字符串的事实,并找出一个LIKE子句来查找匹配的记录。PHP序列化数据的方式很容易弄清楚(提示:这些数字表示事物的长度)。
现在,如果您的序列化数组相当复杂,这将快速崩溃。但是,如果它是一个平面数组,你应该能够做到这一点。
当然,您将使用LIKE '%...%',因此您将不会从任何指示中获得任何帮助,并且性能将非常差。
这就是为什么人们建议你以某种规范化的方式存储这些数据,如果你需要查询“内部”它。
如果您控制了数据模型,那么从长远来看,将序列化的数据填充到数据库中几乎总是会咬你一口。但是,通常人们无法控制数据模型,例如在使用某些开源内容管理系统时。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";}
看到那个“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之后的一切,外层的两个清理了剩下的东西。
这种复杂的黑客行为不是你想要的运行不止一次的代码,更多的是一个工具,可以在不诉诸于编写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 的末尾)