在Serialized Array中的where子句中搜索值

时间:2010-07-29 17:49:01

标签: php sql

标题可能令人困惑,但我认为我的疑问很清楚。

我会解释。我在做这个查询:

 $sql = 'SELECT * FROM calendar WHERE day = "'.$day.'" AND month = "'.$month.'" AND year = "'.$year.'" AND realizada = 0 AND colaborador = "What to put here?!"';

但是“colaborador”字段是一个序列化数组。

一个例子,当我print_r反序列化后我的数组的值是这样的:

Array ( [0] => l3gion [1] => Someone [2] => teste )

想象一下,我想在上一个查询中搜索“l3gion”,我该怎么做?

谢谢。

l3gion

3 个答案:

答案 0 :(得分:4)

简短回答:不要将数据序列化到数据库字段中。这就是normalization的用途......

很长的答案是非常难以做到的。你可以搜索colaborador LIKE '%"13gion"%' ...你也可以写一个正则表达式来处理它(并使用MySQL的REGEXP表达式)......

但最好的解决方案是不将序列化数据存储在数据库中......

答案 1 :(得分:4)

如果需要查询数组中的各个元素,请不要存储序列化数组。将每个元素存储在子表中的单个行上,并将其与日历表的主键值相关联:

CREATE TABLE colaboradoras (
  calendar_id INT NOT NULL,
  colaborador VARCHAR(20) NOT NULL,
  FOREIGN KEY (calendar_id) REFERENCES calendar(calendar_id)
);

INSERT INTO colaboradoras VALUES
(1234, 'l3gion'),
(1234, 'Someone'),
(1234, 'teste');

$sql = "SELECT * FROM calendar AS c JOIN colaboradoras AS o 
              ON c.calendar_id = o.calendar_id
        WHERE c.day = $day AND c.month = $month AND c.year = $year 
          AND c.realizada = 0 AND o.colaborador = 'l3gion'";

这是规范化的方法。

如果必须存储序列化数组,则可以查看How FriendFeed Uses MySQL以索引“无模式”数据。但这也涉及为索引创建新表。

如果您真的无法创建任何新表或索引,可以尝试使用LIKEREGEXP,但这两种解决方案效率都很低且容易出错。

SELECT ... WHERE ... AND colaborador REGEXP '[[:<:]]s:6:\"l3gion\";'

你被搞砸了。

答案 2 :(得分:-2)

  

colaborador =“这里放什么?!”

此代码将处理序列化和原始数据,以及数组和纯字符串值。

if (is_string($colaborador)) {
    // prevent errors from showing
    ob_start();
    $data = unserialize($colaborador);
    // $data is now false or output buffer is non-empty if $colaborador was
    // not serialized
    $data = ob_get_length() > 0 || false === $data ? $colaborador : $data;
    // lose the possible error
    ob_end_clean();
} else {
    $data = $colaborador;
}
// use the first value as colaborador if an array
$sql = 'SELECT * FROM calendar WHERE day = "'.$day.'" AND month = "'.$month.'"
AND year = "'.$year.'" AND realizada = 0 AND colaborador = \'' .
(is_array($data) ? (empty($data) ? '' : $data[0]) : $data) . '\'';`

或者如果你想搜索所有这些:

$sql = 'SELECT * FROM calendar WHERE day = "'.$day.'" AND month = "'.$month.'"
AND year = "'.$year.'" AND realizada = 0 AND colaborador = IN (\'' .
(is_array($data) ? (empty($data) ? '' : implode("', '", $data[0])) : $data) . '\')';`