向pg_query_params数组添加参数会产生错误

时间:2015-04-06 17:52:05

标签: php postgresql

这有效:

$entriesResult = pg_query_params("
SELECT * FROM crosstab(
    $$
    SELECT entry_id, field_id, COALESCE(d.data, f.default_val) AS data
    FROM   entry     e
    JOIN   field     f USING (section_id)
    LEFT   JOIN data d USING (field_id, entry_id)
    WHERE  e.section_id = 1 AND f.aggregate = 1 AND f.enabled = 1 AND f.deleted = 0
    ORDER  BY 1, 2
    $$
    ,
    $$
    SELECT field_id FROM field WHERE section_id = 1 AND aggregate = 1 AND enabled = 1 AND deleted = 0 ORDER BY rank
    $$
)
AS ct (entry_id int $fieldPrefixString)
ORDER  BY f1->>'value' DESC
", array());

这会产生此错误:绑定消息提供1个参数,但预备语句“”需要0

$entriesResult = pg_query_params("
SELECT * FROM crosstab(
    $$
    SELECT entry_id, field_id, COALESCE(d.data, f.default_val) AS data
    FROM   entry     e
    JOIN   field     f USING (section_id)
    LEFT   JOIN data d USING (field_id, entry_id)
    WHERE  e.section_id = $1 AND f.aggregate = 1 AND f.enabled = 1 AND f.deleted = 0
    ORDER  BY 1, 2
    $$
    ,
    $$
    SELECT field_id FROM field WHERE section_id = $1 AND aggregate = 1 AND enabled = 1 AND deleted = 0 ORDER BY rank
    $$
)
AS ct (entry_id int $fieldPrefixString)
ORDER  BY f1->>'value' DESC
", array(3));

不同之处在于我在第二个非工作示例中使用了数组参数。我猜它与使用交叉表有关?如何使用pg_query_params来完成这项工作?

作为最后的手段,我可​​以使用pg_escape_id,但这并不理想。

1 个答案:

答案 0 :(得分:2)

这与crosstab没有直接关系,但与$1没有在文字字符串中进行插值。写这个时你会得到同样的错误:

pg_query_params('SELECT $$ $1 $$', array(3));

$N参数必须独立存在,就好像它们是表达式一样。

所以它可以这样编写,仍然使用$$样式引用:

$entriesResult = pg_query_params("
SELECT * FROM crosstab(
    $$
    SELECT entry_id, field_id, COALESCE(d.data, f.default_val) AS data
    FROM   entry     e
    JOIN   field     f USING (section_id)
    LEFT   JOIN data d USING (field_id, entry_id)
    WHERE  e.section_id = $$ || cast($1 as text) || $$ AND f.aggregate = 1 AND f.enabled = 1 AND f.deleted = 0
    ORDER  BY 1, 2
    $$
    ,
    $$
    SELECT field_id FROM field WHERE section_id = $$ || cast($1 as text) || $$ AND aggregate = 1 AND enabled = 1 AND deleted = 0 ORDER BY rank
    $$
)
AS ct (entry_id int $fieldPrefixString)
ORDER  BY f1->>'value' DESC
", array(3));

在此版本中,$1将被解析为SQL级别的参数。我使用显式转换cast($1 as text),因为它不会使参数成为字符串的任何歧义,无论它最初是什么类型。