2012-06-18 10 views
5

Ho una coppia di colonne che sono state purtroppo definite in modo errato come TIMESTAMP(6) anziché TIMESTAMP(6) WITH TIME ZONE. Mi piacerebbe migrare quelle colonne dal vecchio, datatype errato al nuovo, quello corretto. Inoltre, i valori sembrano essere stati acquisiti in E (S | D) T e ho bisogno del valore in UTC.Come aggiornare una colonna TIMESTAMP a TIMESTAMP WITH TIME ZONE in Oracle

Finora, il migliore che ho avuto è:

alter table OOPSIE_TABLE add (
    NEW_COLUMN_A timestamp(6) with time zone, 
    NEW_COLUMN_B timestamp(6) with time zone 
); 
update OOPSIE_TABLE set 
    NEW_COLUMN_A = COLUMN_A, 
    NEW_COLUMN_B = COLUMN_B 
; 
alter table OOPSIE_TABLE drop column (
    COLUMN_A, 
    COLUMN_B 
); 
alter table OOPSIE_TABLE rename column NEW_COLUMN_A to COLUMN_A; 
alter table OOPSIE_TABLE rename column NEW_COLUMN_B to COLUMN_B; 

Purtroppo, che mi lascia con i dati che assomiglia 15-JUN-12 05.46.29.600102000 PM -04:00, quando voglio 15-JUN-12 09.46.29.600102000 PM UTC (o comunque Oracle sarebbe formattarla).

Ho fatto select dbtimezone from dual; e mi mostra +00:00, quindi non sono sicuro di come procedere. Idealmente, sarei in grado di farlo in puro DML, e farlo tenere conto dell'ora legale in base ai vecchi valori di data (che sono sicuro siano nel fuso orario America/New_York).

risposta

3

Con un little help from @JustinCave, sono arrivato alla seguente soluzione, che compie esattamente quello che volevo:

-- Rename the old columns so we can use them as a data source *AND* so 
-- we can roll back to them if necessary. 
alter table OOPSIE_TABLE rename column COLUMN_A to OLD_COLUMN_A; 
alter table OOPSIE_TABLE rename column COLUMN_B to OLD_COLUMN_B; 
-- Define COLUMN_A and COLUMN_B to have TIME ZONE support. 
alter table OOPSIE_TABLE add (
    COLUMN_A timestamp(6) with time zone, 
    COLUMN_B timestamp(6) with time zone 
); 
-- Populate the "new" columns with the adjusted version of the old data. 
update OOPSIE_TABLE set 
    COLUMN_A = from_tz(OLD_COLUMN_A, 'America/New_York') at time zone 'UTC', 
    COLUMN_B = from_tz(OLD_COLUMN_B, 'America/New_York') at time zone 'UTC' 
; 
2

Per me sembra buono.

`SELECT SYS_EXTRACT_UTC(TIMESTAMP '2012-06-15 05:46:20 -04:00') FROM DUAL;` 

dà:

2012-06-15 09:46:20 

È sufficiente vivere in campagna con differenza 4 ora UTC.

provare anche qualcosa di simile:

SELECT to_char(new_column_a, 'YYYY-MM-DD HH24:MI:SS TZD'), sys_extract_utc(new_column_a) FROM oopsie_table; 
+0

Sì, io vivo in un fuso orario che è attualmente un offset di 4 ore, ma ho Oracle configurato per default su UTC (o almeno ho provato), motivo per cui ho menzionato l'output di 'select dbtimezone from dual;'. Sperimenterò con 'TO_CHAR' per vedere se posso usarlo per cambiare il formato del valore memorizzato nella nuova colonna. –