【问题标题】:Varchar to timestamp PostgreSQLVarchar 到时间戳 PostgreSQL
【发布时间】:2017-05-03 21:30:47
【问题描述】:

我想要做的是将我的日期列类型从 varchar 更改为不带时区的时间戳,并迁移我的所有数据。这就是我正在做的事情:

ALTER TABLE mytable ALTER COLUMN "datecol"
    TYPE timestamp without time zone USING(to_timestamp("datecol", 'YYYY-MM-DD')::timestamp without time zone);

如果 datecol 中的数据采用日期格式,则此方法可以正常工作。但是,如果我有一些无效数据,例如随机字符串(例如“abc”),我如何验证并检查日期格式是否正确?我想为那些无效字段设置默认值。

编辑:感谢路德维格,我解决了我的问题:

create or replace function is_date(s varchar) returns boolean as $$
begin
perform s::date;
return true;
exception when others then
return false;
end;
$$ language plpgsql;

ALTER TABLE mytable ALTER COLUMN "datecol"
TYPE timestamp without time zone USING(
CASE WHEN is_date("datecol") = true
THEN to_timestamp("datecol", 'YYYY-MM-DD')::timestamp without time zone
ELSE '1970-01-01 00:00:00.000'
END
);

【问题讨论】:

  • This answer 可能对你有帮助。
  • date format is good 哪种日期格式好?只有这样:'YYYY-MM-DD'?
  • 不,to_timestamp 识别格式如下:YYYY、YYYY-MM、YYYY-MM-DD、YYYY/MM/DD、YYYY.MM.DD 等。对于这些格式,它可以正常工作

标签: sql database postgresql


【解决方案1】:

您不能使用 try/catch 逻辑更改列的类型,因此您必须正则表达式所有可能的格式,或者您可以:

  1. 添加时间戳数据类型的列“ts”
  2. 添加列“exc”布尔值
  3. do $$ 
      declare _r record; 
    begin 
      for _r in (select * from mytable) loop 
        update mytable set "ts" = to_timestamp("datecol", 'YYYY-MM-DD') 
        where ...PK..=_r.PK; 
      when others 
        then update mytable set "exc" = true; 
     end loop; end; $$;
    
  4. 删除 datecol,将“ts”重命名为“datecol”
  5. 处理“exc”的值

大减号将更改 mytable 中列的顺序。抱歉,您可以在create table tt as select NEEDED order from mytable; drop table mytable;alter table tt rename to mytable 之后道歉,但是您当然也必须重建所有参考资料和家属。或者更奇特的方式 - 你可以开始按需要的顺序添加列,放弃重命名直到你得到旧的集合......

【讨论】:

  • 谢谢,但改变的顺序并不是我真正需要的:D
【解决方案2】:

我将创建一个函数来尝试使用不同的格式进行转换并返回默认日期,以防它们都不起作用,而不是测试有效日期:

create or replace function convert_date(s varchar) 
   returns timestamp 
as 
$$
begin
  -- test standard ISO format
  begin
    return to_timestamp(s, 'yyyy-mm-dd');
  exception when others then
      -- ignore
  end;

  begin
    return to_timestamp(s, 'yyyy.mm.dd');
  exception when others then
    -- ignore
  end;

  begin
    return to_timestamp(s, 'yyyy/mm/dd');
  exception when others then
    -- ignore
  end;

  begin
    return to_timestamp(s, 'yyyy-mm');
  exception when others then
    -- ignore
  end;


  begin
    return to_timestamp(s, 'yyyy');
  exception when others then
    -- ignore
  end;

  return timestamp '1970-01-01 00:00:00';
end
$$ language plpgsql;

然后使用:

ALTER TABLE mytable 
    ALTER COLUMN "datecol" TYPE timestamp without time zone 
    USING (convert_date(datecol));

这不会很有效,但对于一次性工作来说它应该可以工作

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多