这有效:
$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,但这并不理想。
答案 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)
,因为它不会使参数成为字符串的任何歧义,无论它最初是什么类型。