MySQL提取SELECT中的几个子串,任意次数

MySQL extract several substrings in SELECT, an arbitrary number of times

所以我项目的前任编码员决定将 PHP 序列化信息放入 MySQL 数据库中,如下所示:

a:2:{s:6:"Format";s:4:"NTSC";s:7:"License";s:4:"Home";}

或者

a:1:{s:4:"Size";s:1:"S";}

我需要直接使用 MySQL 提取引号之间的内容,以显示:

Format: NTSC, License: Home

或者

Size: S

所以我基本上需要保留引号之间的内容并将其连接起来。我可以使用类似 Looking to extract data between parentheses in a string via MYSQL or MySQL: Use REGEX to extract string (select REGEX) 的东西,但我不能,因为属性的数量是任意的(0,1,2,3,...)而不是总是 2 例如。

有什么办法吗?

写一个PHP脚本反序列化并打印出来。这比使用正则表达式更容易。

反序列化 PHP: 最好的选择就是反序列化它,连接它并交给你的客户(为了提高性能,你会在带来之前缩小行数他们 PHP).

<?php
$data='a:2:{s:6:"Format";s:4:"NTSC";s:7:"License";s:4:"Home";}';

/* To unserialize and print */
$arr=unserialize($data); $out="";
foreach ($arr as $k => $val) {
    $out.=$k.":".$val." ";
}
print "$out<br>";
?>

PHP 中的模式匹配: 下一个选项是在 PHP 中进行正则表达式匹配(尽管这样做没有太大好处。反序列化更好)。我将把这个例子留在这里,以防万一你想用正则表达式匹配做一些事情。

<?php

$data='a:2:{s:6:"Format";s:4:"NTSC";s:7:"License";s:4:"Home";}';
preg_match_all('/"(.*?)"/',$data, $result);

$out="";
for ($i = 0; $i < count($result[0]); $i+=2) {
    print $result[1][$i].":".$result[1][$i+1]." ";
}
print "$out<br>";
?>

Export,Process,Import: 如果 table 列不再以序列化格式写入,并且仅被读取(返回遗留数据),您可以将其导出为 csv 文件,在 perl 中处理数据,添加一个新列以包含由空格分隔的 "Tag=Value" 格式,然后将文件导入回数据库中,其中包含一个新列新数据被插入。如果您需要它,我可以为您提供一个 perl 脚本来 parse/convert 序列化数据。

MySql 中使用 UDF 的模式匹配: 另一方面,如果您只想在 MySql 查询本身中使用正则表达式(以提取 tag/values),你可以使用这个 extension。它需要从源代码构建,安装。


回答有关 RLIKE 的问题:如果您知道序列化数据的所有可能格式(如果它对您来说看起来足够简单),您可以 运行 在将行放入 [=38] 之前进行正则表达式匹配=](如果性能很重要)。

create table tt (data varchar(100));
insert into tt values ("a:2:{s:6:\"Format\";s:4:\"NTSC\";s:7:\"License\";s:4:\"Home\";}");

select data from tt where data rlike '"Format";s:[0-9]+:"NTSC"';