2013-12-08 213 views
2

我有一个表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. 

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

更新:

试图与另一个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日期样式

show datestyle; 
"ISO, DMY" 

回答

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) 
+0

我需要在'DD-MM-YY'格式的所有expirydates和Postgres的8.4我使用,它剂量明白'\ d' –

+0

'select to_date(替换(substring('LA20683_30_04_2015'from'[0-9] + [-_] [0-9] + [-_] [0-9] + $ '),'_',' - '),'DD-MM-YY');'给我这个答案''3915-04-30“' –

+0

你有可能使用8.4〜\\ d的双反斜杠。但很奇怪 - 在9.4我得到了一个正确的答案。是的,8.4上有一个错误。它对模式的错误不太宽容。 –