Php 从序列化数组中搜索where子句中的值

Php 从序列化数组中搜索where子句中的值,php,sql,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”是一个序列化数组 例如,当我在取消序列化后打印数组的值时,它是这

标题可能会让人困惑,但我想我的怀疑是清楚的

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

 $sql = 'SELECT * FROM calendar WHERE day = "'.$day.'" AND month = "'.$month.'" AND year = "'.$year.'" AND realizada = 0 AND colaborador = "What to put here?!"';
但是字段“colaborador”是一个序列化数组

例如,当我在取消序列化后打印数组的值时,它是这样的:

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

假设我想在上一个查询中搜索“l3gion”,我该怎么做

多谢各位


l3gion

简单的回答是:不要将数据序列化到数据库字段中。这就是为什么

答案很长,这将是非常困难的。您可以搜索像“%”13gion“%”这样的
colaborador
。。。您也可以编写一个正则表达式来处理它(并使用MySQL的表达式)


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

简单的回答是:不要将数据序列化到数据库字段中。这就是为什么

答案很长,这将是非常困难的。您可以搜索像“%”13gion“%”这样的
colaborador
。。。您也可以编写一个正则表达式来处理它(并使用MySQL的表达式)

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

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) . '\')';`
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) . '\')';`

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

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'";
这是标准化方法

如果必须存储序列化数组,则可以签出以索引“无模式”数据。但这也包括为索引创建新表

如果确实无法创建任何新的表或索引,可以尝试使用
LIKE
REGEXP
,但这两种解决方案都非常低效且容易出错

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

选择。。。哪里和colaborador REGEXP'[[:如果需要从数组中查询单个元素,请不要存储序列化数组。将每个元素存储在子表中的单个行上,并将其与日历表的主键值关联:

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'";
这是标准化方法

如果必须存储序列化数组,则可以签出以索引“无模式”数据。但这还涉及为索引创建新表

如果确实无法创建任何新的表或索引,可以尝试使用
LIKE
REGEXP
,但这两种解决方案都非常低效且容易出错

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


选择…WHERE…和colaborador REGEXP'[[:最好的解决方案是不要序列化您要搜索的数据。在某些情况下,将序列化数据存储在DB中确实是个好主意,因为DB being normalized可能会扩展到太多的表。@Kirzilla:我不同意。手工编辑非常困难。除了PHP程序之外,它对任何东西都没有意义。我可能会承认存储JSON string,但不是序列化的值…@Kirzilla:是的,因为我们的表快用完了!我在我的表中使用了序列化。将数据库体系结构重构为多个表而不是序列化的数据是否更好?我还尝试使用LIKE运算符搜索它们,它似乎工作得很好(至少目前是这样)。最好的解决方案是不要序列化您将要搜索的数据。在某些情况下,将序列化数据存储在DB中确实是个好主意,因为DB being normalized可能会扩展到太多的表。@Kirzilla:我不同意。手工编辑非常困难。除了PHP程序之外,它对任何东西都没有意义。我可能会承认存储JSON string、 但不是序列化的值…@Kirzilla:是的,因为我们的表快用完了!我在表中使用了序列化,将数据库体系结构重构为多个表而不是序列化的数据是否更好?我还尝试使用LIKE运算符搜索它们,似乎效果很好(至少目前如此)。答案很简单。永远不要在数据库中存储序列化数据。给自己买一本关于数据库基础知识的书。或者,如果你确实存储了序列化数据,不要期望能够使用SQL查询其中的单个元素。答案很简单。永远不要在数据库中存储序列化数据。给自己买一本关于数据库基础知识的书。或者如果你确实存储了se已序列化的数据,不要期望能够使用SQL查询其中的单个元素。除了使用输出缓冲区尝试检测未序列化错误的恐怖之外,他还询问在数据库中搜索序列化值,而不是使用序列化值作为搜索文本…@ircmaxell:这是捕获未序列化数据的唯一方法启用错误报告时lize失败(默认情况,可能是l3gion的情况)。搜索序列化数据是我阅读问题的方式。您可以使用
$php\u errormsg
$php\u errormsg='';$data=@unserialize($foo);$data=empty($php\u errormsg)?$data:$foo;
或者,最好使用错误异常。但请不要这样滥用输出缓冲(这只会使维护几乎不可能)…@ircmaxell:unserialize会发布一个E_通知,该通知会打印到浏览器中。除非您更改默认设置,否则会出现这种情况。需要输出缓冲来捕捉这种情况。如果您足够聪明以减少错误报告,那么您就足够聪明地理解,在您的情况下,您不需要输出缓冲。除了使用输出缓冲的恐怖之外呃,为了检测非序列化的错误,他询问在