【发布时间】:2011-03-17 07:14:03
【问题描述】:
我有一个列值存储在数据库中:
a:2:{i:0;s:2:"US";i:1;s:2:"19";}
我想在 mysql 查询期间对其进行反序列化,而不是在获取数据后使用 php unserialize 函数。
我想这样做,这样我就可以使用序列化值加入另一个表。这将避免在使用 php 反序列化后执行单独的查询,仅针对连接的数据。
【问题讨论】:
标签: mysql
我有一个列值存储在数据库中:
a:2:{i:0;s:2:"US";i:1;s:2:"19";}
我想在 mysql 查询期间对其进行反序列化,而不是在获取数据后使用 php unserialize 函数。
我想这样做,这样我就可以使用序列化值加入另一个表。这将避免在使用 php 反序列化后执行单独的查询,仅针对连接的数据。
【问题讨论】:
标签: mysql
MySQL 不知道 PHP 序列化是什么。你做不到。
【讨论】:
JOIN 操作,您应该真的重新考虑您的数据库设计。这要求进一步normalization。
You can't do it 部分最好改成It's very hard to achieve and probably not the best way to do it。如果您能想到解决问题的替代方案,那就更好了。
您可以使用SUBSTRING_INDEX
例如,如果您有这样的记录:
a:5:{s:9:"invoiceid";s:1:"8";s:8:"balance";i:5;s:14:"broughtforward";i:3;s:6:"userid";s:5:"13908";s:10:"customerid";s:1:"3";}
您可以使用以下 SELECT 语句:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(old_data,';',1),':',-1) AS fieldname1,
SUBSTRING_INDEX(SUBSTRING_INDEX(old_data,';',2),':',-1) AS fieldvalue1,
SUBSTRING_INDEX(SUBSTRING_INDEX(old_data,';',3),':',-1) AS fieldname2,
SUBSTRING_INDEX(SUBSTRING_INDEX(old_data,';',4),':',-1) AS fieldvalue2,
SUBSTRING_INDEX(SUBSTRING_INDEX(old_data,';',5),':',-1) AS fieldname3,
SUBSTRING_INDEX(SUBSTRING_INDEX(old_data,';',6),':',-1) AS fieldvalue3,
SUBSTRING_INDEX(SUBSTRING_INDEX(old_data,';',7),':',-1) AS fieldname4,
SUBSTRING_INDEX(SUBSTRING_INDEX(old_data,';',8),':',-1) AS fieldvalue4,
SUBSTRING_INDEX(SUBSTRING_INDEX(old_data,';',9),':',-1) AS fieldname5,
SUBSTRING_INDEX(SUBSTRING_INDEX(old_data,';',10),':',-1) AS fieldvalue5
FROM table;
查看此内容以供参考:How to unserialize data using mysql without using php
【讨论】:
SUBSTRING_INDEX(SUBSTRING_INDEX(old_data, '";', 2), ':"', -1) fieldvalue1,尽管这确实意味着如果您不幸在数据中包含该组合,那么您可能完全不走运,因为您没有其他东西可以真正从规范中搜索,除非您有某种正则表达式或模糊值之前的长度数。
这个怎么样?这是一个带有嵌入式php的MySQL用户定义函数:
CREATE FUNCTION unserialize_php RETURNS STRING SONAME 'unserialize_php.so';
用法示例:
SELECT unserialize_php('O:8:"stdClass":2:{s:1:"a";s:4:"aaaa";s:1:"b";s:4:"bbbb";}', "$obj->a")
AS 'unserialized';
+---------------+
|未序列化 |
+---------------+
|啊啊啊
+---------------+
一组中的 1 行(0.00 秒)
drop function unserialize_php;
来源:https://github.com/junamai2000/mysql_unserialize_php
您可以创建一个 MySQL 用户定义函数并在函数内部调用 zend_eval_string,以便您可以将 PHP 变量带回 MySQL 结果。我实现了一个示例程序。你可以试试看。
【讨论】:
来自http://www.blastar.biz/2013/11/28/how-to-use-mysql-to-search-in-php-serialized-fields/
标准数组
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".*'
【讨论】:
向数据库添加依赖于编程语言的结构是一种非常糟糕的做法。如果你这样做,你总是不得不依赖这种语言。
最好的方法是规范化表结构(不同的字段或表)。
下一种方法是将数据保存为分隔字符串(例如:0,US,1,19)。然后可以使用 MySQL 的SUBSTRING() 或者使用 JSON 编码等标准序列化机制。
【讨论】:
正如kchteam 所提到的,MySQLToolBox 库使用自定义定义的 MySQL 函数getPhpSerializedArrayValueByKey 可在此处获得https://github.com/KredytyChwilowki/MySQLToolBox/blob/master/getPhpSerializedArrayValueByKey.sql 非常方便。
添加此函数后,您可以使用以下语法检索序列化数组中的任何值,
SELECT getPhpSerializedArrayValueByKey(column_name, 'array_key') AS deseializedArrayValue FROM table_name
给定的数组可以像这样被反序列化,
SELECT getPhpSerializedArrayValueByKey('a:2:{i:0;s:2:"US";i:1;s:2:"19";}
', 'key_to_retrieve') AS key_to_retrieve
【讨论】:
对于序列化数组你可以使用来自here的函数getPhpSerializedArrayValueByKey
【讨论】:
你可以通过这种方式简单地加入你的桌子
SELECT
table_to_join.ID as table_to_join_ID ,
serialized_table.ID AS serialized_table_ID,
FROM
table_to_join
LEFT JOIN
serialized_table ON serialized_table.array_field REGEXP CONCAT_WS('','.s:[0-9];s:', table_to_join.ID ,';.') ;
请注意。我在表中使用从 0 到 9 的索引。如果您有其他索引,则必须更正正则表达式
【讨论】: