mysql在序列化数组中选择查询

Dae*_*lan 17 php mysql arrays

我将数据列表存储在数据库中的字段中的序列化数组中(我使用的是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.我的第二反应是:为什么?在理智的事情可以是:

  1. 将数组检索到PHP中,对其进行反序列化并在其中进行搜索
  2. 忘记将数据存储在MySQL中作为序列化并将其存储为常规表并将其编入索引以便快速搜索

我会选择第二种选择,但我不知道你的背景.

当然,如果你真的想要,你可以尝试使用SUBSTRING其他MySQL功能,并尝试操作该字段,但我不明白你为什么要这样做.这很麻烦,这将是一个不必要的丑陋黑客.另一方面,这是一个谜题,这里的人往往喜欢谜题,所以如果你真的想发布你的领域的内容,我们可以给它一个镜头.

  • > _"OMG.我的第二反应是:为什么?明智的做法是:"_如何居高临下.通常情况下,当使用像Drupal和WordPress这样的CMS系统时,你无法控制其他一些盲目程序员存储数据的格式. (4认同)

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的末尾)

  • 这比之前的评论更有帮助......就像你说的,Drupal/Ubercart 对此感到内疚,所以告诉人们他们应该重建房子,而他们所要求的只是如何更换灯泡并不完全有帮助 (3认同)
  • > _"但是,通常情况下,人们无法控制数据模型,例如在使用某些开源内容管理系统时."_这就是所有其他人在报告不使用人员时的报价关系形式的日期.你无法解决别人的罪恶! (2认同)

小智 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)

希望这能有所帮助!