Yog*_*sch 7 postgresql datatypes parameter interval postgresql-10
上下文正在从其余服务器连接到 Postgres 数据库。
考虑一个假设的代表性示例:我希望能够获取帐户创建日期比任意值早/新的名称列表。
在下面的示例查询中,表结构很简单 -name
是 type text
,并且creation_date
是 type timestamp
。所以当我做类似的事情时
server_pg_module:query("select name from new_table where
current_timestamp - creation_date < '6 days'")
Run Code Online (Sandbox Code Playgroud)
它工作得很好。但我真正想做的是6 days
从服务器获取该值。所以我尝试像
server_pg_module:query("select name from new_table where
current_timestamp - timestamp < $1", ["6 days"]
Run Code Online (Sandbox Code Playgroud)
它抛出一个错误。我试过'6 days'
,"'6 days'"
以及其他一些混合物,都抛出错误。所以为了检查我添加了一个新interval
的类型列interval
并尝试了一个查询
server_pg_module:query("insert into new_table (name, interval) values ($1, '3 day')", ["fooo"]).
Run Code Online (Sandbox Code Playgroud)
哪个有效,但是
server_pg_module:query("insert into new_table (name, interval) values ($1, $2)", ["fooo", "3 days"]).
Run Code Online (Sandbox Code Playgroud)
休息。为了更好的衡量,除了"'3 days'"
上面提到的混合物之外,我还尝试过$2::interval
(我不确定是否合法),但它不起作用。
因此,我相信它可能与在 param 查询中表达间隔有关,或者与我正在使用的模块有关。关于导致问题的原因以及如何做这类事情的任何想法都将不胜感激。或者可能可以缩小问题不在于 pg 而在于模块,然后我必须在其他地方解决它。
Postgres 版本:10.x
我使用的模块是 pgo(用于 Erlang 编程语言)https://github.com/SpaceTime-IoT/pgo。我得到的错误消息(当我传递"2 days"
或"'2 days'"
作为查询参数)看起来像:
{error,{pgsql_error,#{code => <<"08P01">>,file => <<"pqformat.c">>,
line => <<"575">>,
message => <<"insufficient data left in message">>,
routine => <<"pq_copymsgbytes">>,severity => <<"ERROR">>,
{unknown,86} => <<"ERROR">>}}}
Run Code Online (Sandbox Code Playgroud)
当我'2 days'
作为参数传递时,它会引发badarg
错误。
TLDR:跳到下面的“高级查询”一章。
您没有透露您正在使用的模块,但问题显然是类型转换之一。看起来您的参数是作为类型值传递的,我假设text
or varchar
。text
->没有隐式类型转换interval
:
Run Code Online (Sandbox Code Playgroud)SELECT castsource::regtype, casttarget::regtype, castcontext FROM pg_cast WHERE casttarget = 'interval'::regtype;
铸源| 投靶| 演员表 :--------------------- | :--------- | :---------- 没有时区的时间| 间隔| 一世 间隔| 间隔| 一世
db<>在这里摆弄
如果我的假设是正确的,您应该会看到如下错误消息:
Run Code Online (Sandbox Code Playgroud)ERROR: operator does not exist: interval < text
我非常有信心您未公开的模块有方法传递不同的数据类型或无类型的字符串文字。Postgres 确实提供了这个功能。
您还声明:
我也试过
$2::interval
这很奇怪,因为显式类型转换也应该有效。
Run Code Online (Sandbox Code Playgroud)-- interval typed value SELECT current_timestamp - timestamp '2018-05-04 18:40' < interval '6 days'; -- works
| ?柱子?| | :------- | | f |
Run Code Online (Sandbox Code Playgroud)--untyped string literal SELECT current_timestamp - timestamp '2018-05-04 18:40' < '6 days'; -- works
| ?柱子?| | :------- | | f |
Run Code Online (Sandbox Code Playgroud)-- text typed value SELECT current_timestamp - timestamp '2018-05-04 18:40' < text '6 days'; -- fails!
错误:运算符不存在:间隔 < 文本
第 2 行:... current_timestamp - timestamp '2018-05-04 18:40' < text '6 ... ^ 提示:没有运算符匹配给定的名称和参数类型。您可能需要添加显式类型转换。
Run Code Online (Sandbox Code Playgroud)-- text typed value, with explicit cast SELECT current_timestamp - timestamp '2018-05-04 18:40' < ('6 days'::text::interval); -- works
| ?柱子?| | :------- | | f |
准备好的语句也是如此:
Run Code Online (Sandbox Code Playgroud)PREPARE fooplan_typed_interval(interval) AS SELECT current_timestamp - timestamp '2018-05-04 18:40' < $1; EXECUTE fooplan_typed_interval('6 days');
| ?柱子?| | :------- | | f |
Run Code Online (Sandbox Code Playgroud)PREPARE fooplan_untyped AS SELECT current_timestamp - timestamp '2018-05-04 18:40' < $1; EXECUTE fooplan_untyped('6 days');
| ?柱子?| | :------- | | f |
Run Code Online (Sandbox Code Playgroud)PREPARE fooplan_typed_text(text) AS SELECT current_timestamp - timestamp '2018-05-04 18:40' < $1; EXECUTE fooplan_typed_text('6 days'); -- only this one fails!
错误:运算符不存在:间隔 < 文本
第 3 行:...ELECT current_timestamp - 时间戳 '2018-05-04 18:40' < $1; ^ 提示:没有运算符匹配给定的名称和参数类型。您可能需要添加显式类型转换。
Run Code Online (Sandbox Code Playgroud)PREPARE fooplan_typed_text(text) AS SELECT current_timestamp - timestamp '2018-05-04 18:40' < $1::interval; EXECUTE fooplan_typed_text('6 days');
| ?柱子?| | :------- | | f |
db<>在这里摆弄
除此之外,您的任何查询都不能使用索引(不是“sargable”)。 改用这样的东西!
server_pg_module:query("select name from new_table
where creation_date > localtimestamp - interval '1 day' * $1", [6])
Run Code Online (Sandbox Code Playgroud)
您可以将interval
与相乘integer
。
或者,如果您发现传递类型参数的问题:
server_pg_module:query("select name from new_table
where creation_date > localtimestamp - $1::interval", ['6 days'])
Run Code Online (Sandbox Code Playgroud)
采用localtimestamp
指出,“当前时间”取决于与类型当前时区设置timestamp
。细节:
归档时间: |
|
查看次数: |
5437 次 |
最近记录: |