更新范围类型的下限/上限

时间:2013-08-09 11:39:26

标签: postgresql

我有tstzrange类型的列(带时区范围的时间戳),我只需更新此值的上限或下限(并保持包含/独占边界)

我设法改变了

(-infinity,infinity)

UPDATE table
SET
    my_column = tstzrange(
        lower(my_column),
        now(),
        '()'
    )

我有

(-infinity, <current timestamp>)

但我不知道如何保持默认范围的边界..这甚至会将[ ]更改为( )

3 个答案:

答案 0 :(得分:4)

found function我错过了,有可能这样做

UPDATE table
SET
    my_column = tstzrange(
        lower(my_column),
        now(),
        concat(
            CASE WHEN lower_inc(my_column) THEN '[' ELSE '(' END,
            CASE WHEN upper_inc(my_column) THEN ']' ELSE ')' END
        )
    )

最好为此创建功能。或者还有其他(更简单/更好)的解决方案吗?

答案 1 :(得分:2)

据我所知,使用CASE WHEN ...是获得界限的最佳方法。以下是一些简单的用户定义函数,它们返回所有本机范围类型的范围界限。

警告:这些函数的行为方式令人惊讶,因为范围类型的行为在sometimes surprising ways

  

内置范围类型 int4range,int8range和daterange 都使用   规范形式,包括下限和排除上部   界;也就是说,[)。

  

虽然这里指定了'(]',但显示的值将是   转换为规范形式,因为int8range是离散范围类型。 。

(强调补充)

PostgreSQL将封闭范围从1到10规范化,半开放范围从1到11。

select int4range('[1,10]');
[1,11)

对于左半开的范围,它也是一样的。

select int4range('(1,10]');
[2,11)

range_bounds()返回结果的边界,而不是输入。

select range_bounds(int4range('(1,10]'));
[)

功能

create or replace function range_bounds(in range int4range)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range int8range)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range numrange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;


create or replace function range_bounds(in range tsrange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range tstzrange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range daterange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

答案 2 :(得分:1)

改进 Mikes great answer

当我们使用伪类型anyrange时,我们只需要一个函数:

CREATE OR REPLACE FUNCTION range_bounds(IN range anyrange)
    RETURNS CHAR(2) AS
$$
SELECT CASE WHEN lower_inc(range) THEN '[' ELSE '(' END ||
       CASE WHEN upper_inc(range) THEN ']' ELSE ')' END;
$$
LANGUAGE SQL
RETURNS NULL ON NULL INPUT;