3

假设我有桌子:

postgres=# create table foo (datetimes timestamptz);
CREATE TABLE
postgres=# \d+ foo 
                            Table "public.foo"
  Column   |           Type           | Modifiers | Storage | Description 
-----------+--------------------------+-----------+---------+-------------
 datetimes | timestamp with time zone |           | plain   | 
Has OIDs: no

所以让我们在其中插入一些值......

postgres=# insert into foo values 
    ('2012-12-12'), --This is the value I want to catch for.
    (null), 
    ('2012-12-12 12:12:12'), 
    ('2012-12-12 12:12');
INSERT 0 4

这就是我们所拥有的:

postgres=# select * from foo ;
       datetimes        
------------------------
 2012-12-12 00:00:00+00

 2012-12-12 12:12:12+00
 2012-12-12 12:12:00+00
(4 rows)

理想情况下,当输入未提供 TIME 时,我想设置一个默认时间戳值,而不是事实上的时间2012-12-1200:00:00我想设置一个默认的15:45:10.

意思是,我的结果应该如下所示:

postgres=# select * from foo ;
       datetimes        
------------------------
 2012-12-12 15:45:10+00    --This one gets the default time.

 2012-12-12 12:12:12+00
 2012-12-12 12:12:00+00
(4 rows)

我不确定如何在 postgres 8.4 中执行此操作,我在手册的datetime部分或有关列默认值的部分中找不到任何内容。

4

1 回答 1

3

可以在BEFORE INSERT触发器中调整新行的值。这样的触发器可以测试 中是否存在非零时间分量NEW.datetimes,如果没有将其设置为所需的固定时间。

但是,在 INSERT 子句中时间部分显式设置为零的情况无法使用此技术处理,因为'2012-12-12'::timestamptz等于'2012-12-12 00:00:00'::timestamptz。所以这就像试图区分 0.0 和 0.00。

从技术上讲,调整值应该发生在从字符串隐式转换为列类型之前,即使是RULE(动态查询重写)也无法做到这一点。

在我看来,最好的选择是重写 INSERT 并对每个值应用一个函数,将其从字符串显式转换为时间戳。此函数将测试输入格式并在需要时添加时间部分:

  create function conv(text) returns timestamptz as $$
    select case when length($1)=10 then ($1||' 15:45:10')::timestamptz
      else $1::timestamptz end; $$
   language sql strict immutable;

insert into foo values 
    (conv('2012-12-12')),
    (conv(null)), 
    (conv('2012-12-12 12:12:12')), 
    (conv('2012-12-12 12:12'));
于 2012-06-13T10:36:41.250 回答