在postgres中标准化日期 - 到目前为止的字符

时间:2013-12-08 07:28:38

标签: postgresql date substring trim to-date

我有一个coloumnname description

的表
description  //character varying
LZ000834_28-02-14
LZ000834_28-02-14
LA20683_30-04-15
LA20683_30-04-15
LA20300_31-01-15
LA20300_31-01-2015
LA20264_31-01-15
LA20264_31-01-2016
LAN2078_31-03-16
LAN2078_31-03-15
LAN8394_31-04-14
L2Z82736_31_03_2015  //has 1million rows

这里的描述是指batchname_expirydate

我的问题是如何规范化我的描述列将所有这些日期转换为DD-MM-YY格式

我尝试了这两个查询

select substring(description from position('_' in description) +1) from attributesetinstance;

上面的查询会给我所有字符串,然后我尝试日期转换,如此

select to_date(substring(description from position('_' in description) +1), 'DD-MM-YY') from attributesetinstance;

现在这给了我错误

ERROR:  invalid value "_3" for "DD"
DETAIL:  Value must be an integer.


********** Error **********

ERROR: invalid value "_3" for "DD"
SQL state: 22007
Detail: Value must be an integer.

如何更新/修改我的所有数据库?

更新

尝试使用另一个sql

with product_dates AS (
select description, ((val[2])||'-'||val[3]||'-'||val[4])::date as expir_date
from ( 
    select description,regexp_matches(description, '([a-zA-Z0-9]+)_([0-9]+)[-_]([0-9]+)[-_]([0-9]+)') as val 
    from attributesetinstance
) a
), expiring_dates AS (
select description from product_dates
)
select description from expiring_dates

我收到以下错误:

ERROR:  date/time field value out of range: "31-04-14"


********** Error **********

ERROR: date/time field value out of range: "31-04-14"
SQL state: 22008

更新

我的postgres datestyle

show datestyle;
"ISO, DMY"

1 个答案:

答案 0 :(得分:1)

此错误消息不太好 - 此日期2014-04-31无效。因此,您无法使用您使用的算法将此字符串转换为日期。但是to_date函数是容错的

postgres=# select '2014-04-31'::date;
ERROR:  date/time field value out of range: "2014-04-31"
LINE 1: select '2014-04-31'::date;
               ^
Time: 0.551 ms
postgres=# select to_date('2014-04-31','YYYY-MM-DD');
  to_date   
────────────
 2014-05-01
(1 row)

此代码有效

 postgres=# select to_date(replace(substring('LA20683_30_04_15' from '\d+[-_]\d+[-_]\d+$'),'_','-'), 'DD-MM-YY');
  to_date   
────────────
 2015-04-30
(1 row)

Time: 57.840 ms
postgres=# select to_date(replace(substring('LA20683_30_04_2015' from '\d+[-_]\d+[-_]\d+$'),'_','-'), 'DD-MM-YY');
  to_date   
────────────
 2015-04-30
(1 row)

8.4的解决方法:

CREATE OR REPLACE FUNCTION to_date_DD_MM_YY_2_4(text)
RETURNS date AS $$
SELECT CASE WHEN $1 ~ e'\\d+-\\d+-\\d{2}$' THEN to_date($1, 'DD-MM-YY') 
                                           ELSE to_date($1, 'DD-MM-YYYY')
       END$$ 
LANGUAGE sql;
CREATE FUNCTION
Time: 25.229 ms

postgres=# SELECT to_date_DD_MM_YY_2_4('30-04-2015');
 to_date_dd_mm_yy_2_4 
----------------------
 2015-04-30
(1 row)