免责声明:我不知道 PHP 或 CodeIgniter,但我愿意断言它们都没有任何内置的 EAV 支持。值得注意的是,我对 EAV 了解很多,所以我会从这个角度回答。
当您撰写有关搜索特定值的文章时,我假设您的意思也是在特定字段中。因此,如上所述,将数据放在表单表之外的 XML CLOB 中(例如数据)并使用 MySQL's XML functions 对其进行搜索。严重地。假设 XML 看起来像:
<data>
<field id="[field_id]">value</field>
</data>
这样搜索:
SELECT f.form_id
FROM
form f
WHERE
f.form_id = ?
AND ExtractValue(data, '//field[@id="[field_id]"]') = ?
为什么?问题是针对 EAV 模型搜索多个标准具有挑战性。考虑这个例子:
SELECT f.form_id
FROM
form f
INNER JOIN form_fields f1 ON f1.form_id = f.form_id
INNER JOIN form_fields f2 ON f2.form_id = f.form_id
WHERE
f.form_id = ?
AND
(f1.field_id = ? AND f1.field_value = ?)
AND
(f2.field_id = ? AND f2.field_value = ?)
这一切看起来都很好,现在将 AND 更改为 OR 并且一切都变得松散了。
SELECT f.form_id
FROM
form f
INNER JOIN form_fields f1 ON f1.form_id = f.form_id
INNER JOIN form_fields f2 ON f2.form_id = f.form_id
WHERE
f.form_id = ?
OR
(f1.field_id = ? AND f1.field_value = ?)
OR
(f2.field_id = ? AND f2.field_value = ?)
你看到问题了吗? FROM 子句中的 INNER JOIN 表示无论如何记录,无论 WHERE 子句都返回数据。因此,EAV 要求在 WHERE 中使用 EXISTS,而不是在 FROM 子句 + WHERE 子句中加入 JOIN:
SELECT f.form_id
FROM
form f
WHERE
f.form_id = ?
AND (
EXISTS (
SELECT f1.form_id FROM form_fields f1
WHERE f1.field_id = ? AND f1.field_value = ? AND f1.form_id = f.form_id
)
-- note OR search
EXISTS (
SELECT f2.form_id FROM form_fields f2
WHERE f2.field_id = ? AND f2.field_value = ? AND f2.form_id = f.form_id
)
)
有点丑是吧?那和MySQL subquery performance is not good。添加搜索特定数据类型(例如日期和整数)的愿望,并且您正在转换或使用 form_field 表中的多个列(例如 field_date_value、field_int_value 等...)。
因此,XML CLOB 意味着查询时只考虑表以及多值属性的可能性(想到多选或复选框)。