我想要做的是将我的日期列类型从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”),我如何验证并检查日期格式是否良好?我想为这些无效字段设置默认值。
编辑:谢谢Ludvig,我解决了我的问题: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
);
答案 0 :(得分:0)
您无法使用try/catch
逻辑更改列的类型,因此您必须重新编写所有可能的格式,或者您可以:
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; $$;
大减号会改变mytable中列的顺序。你可以在create table tt as select NEEDED order from mytable; drop table mytable;alter table tt rename to mytable
之后做出不好的道歉,但是当然你也必须重建所有的引用和依赖。或者甚至更奇特的方式 - 您可以开始按需要的顺序添加列,删除重命名,直到您获得旧的设置...
答案 1 :(得分:0)
我没有测试有效日期,而是创建一个尝试使用不同格式进行投射的函数,并返回默认日期,以防它们都不起作用:
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));
这不会非常有效,但对于一次性工作,它应该有效