我在PostgreSQL数据库中有一个表ACTIVITIES_T
。 ACTIVITY_CODE
是VARCHAR
列:
ID (INT) | ACTIVITY_CODE (VARCHAR) | ACTIVITY_TEXT (VARCHAR)
-------------------------------------------------------------
.. .. ..
7 10012 ..
8 10013 ..
9 10014 ..
10 10015 ..
11 SPECIAL ..
我有一个连续的伪数字块10012..10015
,我需要使用BETWEEN a AND b
运算符或>= n1 and <= n2
进行选择。
但并非ACTIVITY_CODE
中的所有条目都是数值
我试过这个:
select * from activities_t where activity_code::int >= 10012 and
activity_code::int <= 10015;
但得到了错误
ERROR: invalid input syntax for integer: SPECIAL
答案 0 :(得分:4)
SELECT *
FROM activities_t
WHERE CASE WHEN activity_code ~ '^\d+$' -- only digits
THEN activity_code::int BETWEEN 10012 AND 10015 END;
CASE
包装器可以避免异常。仅考虑仅由数字组成的字符串。 (所以也没有空白填充!)
不需要ELSE
,因为CASE
默认为NULL
且只有TRUE
符合WHERE
条款。
当然,这不能在activity_code
上使用任何普通索引。
如果您需要更好的性能,请清理您的表格设计,或者,如果这不是一个选项,请创建表达式索引:
CREATE INDEX foo_idx ON activities_t((CASE WHEN activity_code ~ '^\d+$'
THEN activity_code::int END));
并匹配查询中的表达式:
SELECT *, CASE WHEN activity_code ~ '^\d+$' THEN activity_code::int END
FROM activities_t
WHERE CASE WHEN activity_code ~ '^\d+$'
THEN activity_code::int END BETWEEN 10012 AND 10015;
这与第一个查询略有不同,如果它不会触发索引扫描,则会略贵一些。
答案 1 :(得分:0)
只是添加 @Erwin Brandstetter 所写的内容,如果在Spring Data中使用此内容,则会有关于使用@Query中的::
运算符的投诉。
要解决此问题,请转义::
,如此示例所示,
https://stackoverflow.com/a/43982706/1005607
\\:\\:
或者修改查询以使用cast
函数。
@Query(value="select * from activities_t where " +
" case when activity_code ~ '^\d+$' " + // only digits
" then cast(activity_code as int) between 10012 and 10015 end ",
nativeQuery=true)
public List<ActivityT> getByActivityCodes();