我有以下SQL查询:
SELECT choice, COUNT(*) AS c
FROM Vote, Person
WHERE Vote.pid = Person.pid AND (Person.city = '%s' OR %s IS NULL) <-----
GROUP BY choice
ORDER BY c DESC, choice
我已添加Person.city = '%s' OR %s IS NULL
部分,因此,如果参数为NULL
,则查询将包含所有城市。当参数为NULL
时,此查询可以正常工作,但当我输入非NULL
值时,比如Paris,我收到此错误:
错误:专栏&#34;巴黎&#34;在角色104不存在
据我所知,发生此错误是因为%s
未被引用。但是当我引用它时,如果%s
为NULL,则'%s' IS NULL
不会评估为true。
我如何检查%s
引用时NULL
是否为{{1}}?
答案 0 :(得分:0)
也许你可以试试:
SELECT choice, COUNT(*) AS c
FROM Vote join
Person
on Vote.pid = Person.pid
WHERE (Person.city = '%s' OR '%s' = 'NULL')
GROUP BY choice
ORDER BY c DESC, choice;
您无法明确搜索&#34; NULL&#34;,但这可能是一个很小的代价。
注意我还将连接语法更改为使用显式join
语法。
答案 1 :(得分:0)
如果你的变量不是NULL,你的查询应该是:
SELECT choice, COUNT(*) AS c
FROM Vote as V join
Person as P
on V.pid = P.pid
WHERE P.city = '%s'
GROUP BY choice
ORDER BY c DESC, choice;
...如果%s为NULL:
SELECT choice, COUNT(*) AS c
FROM Vote as V join
Person as P
on V.pid = P.pid
GROUP BY choice
ORDER BY c DESC, choice;
绝对不是最简洁的方式,但肯定是最清晰的。
我最初误解了这个问题,为此我道歉。希望有所帮助...
答案 2 :(得分:0)
您应该使用预备语句。本相关答案中C
的详细说明:
Passing C variables into SQL command
然后将值作为值传递,而不是尝试字符串连接,这也可以打开 SQL注入。
您的查询可能如下所示(在JOIN
和GROUP BY
中使用明确的ORDER BY
语法和位置参数进行了简化:
SELECT v.choice, count(*) AS c
FROM vote v
JOIN person p USING (pid)
WHERE (p.city = $1 OR $1 IS NULL)
GROUP BY 1
ORDER BY 2 DESC, 1;
此处不需要括号 - 仅当您在AND
之前OR
绑定后添加更多条件。
或者您创建一个PL / pgSQL函数,以更智能的方式处理NULL
案例。昨天我写了一个详细的相关答案:
How to remove conditions from WHERE clause if parameters are NULL
如果保证参照完整性(由外键约束强制执行)并且每个投票都有相关人员,则在NULL
值的情况下简化函数调用:
SELECT v.choice, count(*) AS c
FROM vote v
GROUP BY 1
ORDER BY 2 DESC, 1;