本文討論了在A(yíng)mazon RDS和Aurora 中使用PostgreSQL數據庫時(shí),與日期/時(shí)間相關(guān)的函數,并確定PostgreSQL數據庫里的clock_timestamp()函數與Oracle中的SYSDATE函數最匹配。同時(shí)我們可以自定義基于clock_timestamp()的改進(jìn)函數(設置遷移的Oracle數據庫服務(wù)器時(shí)區),具體參考“建議”部分中所述。
作者:Baji Shaik and Sudip Acharya
來(lái)源:https://aws.amazon.com/cn/blogs/database/converting-the-sysdate-function-from-oracle-to-postgresql/
譯者:多米爸比
在A(yíng)WS Cloud 中遷移Oracle數據庫到PostgreSQL數據庫是一個(gè)復雜的過(guò)程,從最初評估階段到遷移轉換階段,多個(gè)階段過(guò)程中會(huì )涉及不同的技術(shù)和技能。有關(guān)遷移過(guò)程的更多信息,請參閱下面幾篇文章:
postgres=> select CURRENT_DATE;current_date--------------2020-01-03(1 row)
postgres=> select CURRENT_TIMESTAMP;current_timestamp-------------------------------2020-01-03 04:38:15.662514+00(1 row)postgres=> select CURRENT_TIMESTAMP(2);current_timestamp---------------------------2020-01-03 04:38:19.75+00(1 row)postgres=> select CURRENT_TIME;current_time--------------------04:40:29.409115+00(1 row)postgres=> select CURRENT_TIME(2);current_time----------------04:40:38.01+00(1 row)
postgres=> select LOCALTIMESTAMP; localtimestamp---------------------------- 2020-01-03 04:42:39.405423(1 row) postgres=> select LOCALTIMESTAMP(2); localtimestamp------------------------ 2020-01-03 04:42:41.97(1 row) postgres=> select LOCALTIME; localtime----------------- 04:42:24.022253(1 row) postgres=> select LOCALTIME(2); localtime------------- 04:42:32.01(1 row)postgres=> begin;BEGINpostgres=> select statement_timestamp(), transaction_timestamp();statement_timestamp | transaction_timestamp-------------------------------+-------------------------------2020-01-03 04:58:39.271915+00 | 2020-01-03 04:58:37.690723+00(1 row)postgres=> select pg_sleep(5);pg_sleep----------(1 row)postgres=> select statement_timestamp(), transaction_timestamp();statement_timestamp | transaction_timestamp-------------------------------+-------------------------------2020-01-03 04:58:49.770003+00 | 2020-01-03 04:58:37.690723+00(1 row)
postgres=> WITH time_testAS (SELECT Statement_timestamp())SELECT *,Pg_sleep(3) AS "<- see the difference ->",Statement_timestamp()FROM time_test;statement_timestamp | <- see the difference -> | statement_timestamp-------------------------------+--------------------------+-------------------------------2020-01-03 05:05:08.458192+00 | | 2020-01-03 05:05:08.458192+00(1 row)postgres=>postgres=> WITH time_testAS (SELECT clock_timestamp())SELECT *,Pg_sleep(3) AS "<- see the difference ->",clock_timestamp()FROM time_test;clock_timestamp | <- see the difference -> | clock_timestamp-------------------------------+--------------------------+-------------------------------2020-01-03 05:05:18.040189+00 | | 2020-01-03 05:05:21.042861+00(1 row)
postgres=> select clock_timestamp(), pg_typeof(clock_timestamp()), timeofday(), pg_typeof(timeofday());clock_timestamp | pg_typeof | timeofday | pg_typeof-------------------------------+--------------------------+-------------------------------------+-----------2020-01-03 05:28:50.203961+00 | timestamp with time zone | Fri Jan 03 05:28:50.203961 2020 UTC | text(1 row)
postgres=> begin;BEGINpostgres=> select now(), transaction_timestamp();now | transaction_timestamp-------------------------------+-------------------------------2020-01-03 05:29:25.805646+00 | 2020-01-03 05:29:25.805646+00(1 row)postgres=> select pg_sleep(3);pg_sleep----------(1 row)postgres=> select now(), transaction_timestamp();now | transaction_timestamp-------------------------------+-------------------------------2020-01-03 05:29:25.805646+00 | 2020-01-03 05:29:25.805646+00(1 row)
SET SERVEROUTPUT ON ;BEGINDBMS_OUTPUT.PUT_LINE('Start : ' || to_char(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));dbms_lock.sleep(30);DBMS_OUTPUT.PUT_LINE('End : ' || to_char(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));END;/Start : 2020-01-03 06:11:06End : 2020-01-03 06:11:36在下面的PostgreSQL代碼示例中,在一個(gè)事務(wù)內,您可以按不同的時(shí)間間隔捕獲不同的PostgreSQL日期和時(shí)間函數返回的時(shí)間。以下代碼在兩者之間休眠15秒,比較之前和之后的結果。確定哪個(gè)函數提供與以下行為相同的輸出值SYSDATE:
DO$BODY$BEGINRAISE NOTICE 'clock_timestamp() : %', clock_timestamp();RAISE NOTICE 'statement_timestamp() : %', statement_timestamp();RAISE NOTICE 'now() : %', now();RAISE NOTICE 'current_timestamp : %', current_timestamp;RAISE NOTICE 'transaction_timestamp() : %', transaction_timestamp();RAISE NOTICE '';RAISE NOTICE 'sleep for 15 secs and see the difference below: %', pg_sleep(15);RAISE NOTICE '';RAISE NOTICE 'clock_timestamp() : %', clock_timestamp();RAISE NOTICE 'statement_timestamp() : %', statement_timestamp();RAISE NOTICE 'now() : %', now();RAISE NOTICE 'current_timestamp : %', current_timestamp;RAISE NOTICE 'transaction_timestamp() : %', transaction_timestamp();END;$BODY$;
NOTICE: clock_timestamp() : 2020-01-03 06:20:52.3715+00NOTICE: statement_timestamp() : 2020-01-03 06:20:52.371345+00NOTICE: now() : 2020-01-03 06:20:52.371345+00NOTICE: current_timestamp : 2020-01-03 06:20:52.371345+00NOTICE: transaction_timestamp() : 2020-01-03 06:20:52.371345+00NOTICE:NOTICE: sleep for 15 secs and see the difference below:NOTICE:NOTICE: clock_timestamp() : 2020-01-03 06:21:07.438274+00NOTICE: statement_timestamp() : 2020-01-03 06:20:52.371345+00NOTICE: now() : 2020-01-03 06:20:52.371345+00NOTICE: current_timestamp : 2020-01-03 06:20:52.371345+00NOTICE: transaction_timestamp() : 2020-01-03 06:20:52.371345+00只有clock_timestamp()函數在單個(gè)事務(wù)中返回不同的時(shí)間信息。因此,最佳匹配替代SYSDATE的PostgreSQL函數是clock_timestamp()。但僅此信息還不夠,因為這些值只是時(shí)間戳值。由于不同的時(shí)區在同一時(shí)間點(diǎn)具有不同的時(shí)間戳值,因此您還必須考慮時(shí)區和DST。否則,您可能會(huì )看到與預期不同的值。
SQL> (select ‘dbtimezone’ as config, dbtimezone as offset from dual) union(select ‘sessiontimezone’ as config, sessiontimezone as offset from dual);CONFIG OFFSET--------------- ------------------------------dbtimezone +00:00sessiontimezone +05:30SQL> select sysdate from dual;SYSDATE03/01/2020 09:56:53SQL> alter session set time_zone = ‘-08:30’;Session altered.SQL> (select ‘dbtimezone’ as config, dbtimezone as offset from dual) union(select ‘sessiontimezone’ as config, sessiontimezone as offset from dual);CONFIG OFFSET--------------- ------------------------------dbtimezone +00:00sessiontimezone. -08:30SQL> select sysdate from dual;SYSDATE03/01/2020 09:57.34
postgres=> show timezone; TimeZone
UTC(1 row) postgres=> select clock_timestamp(); clock_timestamp
2020-01-03 06:25:36.165378+00(1 row) postgres=> set timezone = ‘America/New_York’;SETpostgres=> show timezone; TimeZone
America/New_York(1 row) postgres=> select clock_timestamp(); clock_timestamp
2020-01-03 01:25:49.329555-05(1 row) postgres=>如果這些時(shí)間戳是由不同客戶(hù)端在不同時(shí)區返回并存儲在TIMESTAMP WITHOUT TIME ZONE類(lèi)型列中,則數據會(huì )產(chǎn)生誤導。
postgres=> select n.name, n.abbrev N_abbrev,a.abbrev, n.utc_offset N_utc_offset ,a.utc_offset, n.is_dst N_is_dst, a.is_dstfrom pg_timezone_names n, pg_timezone_abbrevs awhere n.name = a.abbrevand n.utc_offset <> a.utc_offsetorder by 1;name | n_abbrev | abbrev | n_utc_offset | utc_offset | n_is_dst | is_dst------+----------+--------+--------------+------------+----------+--------CET | CEST | CET | 02:00:00 | 01:00:00 | t | fEET | EEST | EET | 03:00:00 | 02:00:00 | t | fMET | MEST | MET | 02:00:00 | 01:00:00 | t | fWET | WEST | WET | 01:00:00 | 00:00:00 | t | f(4 rows)postgres=> show timezone;TimeZone----------UTC(1 row)postgres=> select clock_timestamp();clock_timestamp-------------------------------2020-01-03 06:29:09.672859+00(1 row)postgres=> set session time zone 'MET';SETpostgres=> select clock_timestamp() AT TIME ZONE 'MET';timezone----------------------------2020-01-03 07:29:16.261098(1 row)
postgres=> select clock_timestamp() AT TIME ZONE 'UTC' + interval '02:00:00';?column?----------------------------2020-01-03 08:29:19.732955(1 row)
postgres=> select * from pg_timezone_names where lower(name) like '%berlin%';name | abbrev | utc_offset | is_dst---------------+--------+------------+--------Europe/Berlin | CEST | 02:00:00 | t
SQL> ALTER SESSION SET TIME_ZONE='UTC';Session altered.-- Before DST, 28-OCT-2018 at 00:00:00 UTC equivalent to 28-OCT-2018 at 02:00:00 METSQL> select to_timestamp('2020-01-03 00:00:00','YYYY-MM-DD HH24:MI:SS') at time zone 'MET' from dual;TO_TIMESTAMP('2018-10-2800:00:00','YYYY-MM-DDHH24:MI:SS')ATTIMEZONE'MET'---------------------------------------------------------------------------28-OCT-18 02.00.00.000000000 AM MET-- Before DST, 28-OCT-2018 at 01:00:00 UTC equivalent to 28-OCT-2018 at 02:00:00 METSQL> select to_timestamp('2018-10-28 01:00:00','YYYY-MM-DD HH24:MI:SS') at time zone 'MET' from dual;TO_TIMESTAMP('2018-10-2801:00:00','YYYY-MM-DDHH24:MI:SS')ATTIMEZONE'MET'---------------------------------------------------------------------------28-OCT-18 02.00.00.000000000 AM MET
postgres=> show timezone;TimeZone----------UTC postgres => select '2018-10-28 00:00:00' AT TIME ZONE 'Europe/Berlin';timezone---------------------2018-10-28 02:00:00 postgres => select '2018-10-28 01:00:00' AT TIME ZONE 'Europe/Berlin';timezone---------------------2018-10-28 02:00:00CREATE OR REPLACE FUNCTION <<Your schema>>.sysdate()RETURNS TIMESTAMP WITHOUT TIME ZONEAS$BODY$ SELECT clock_timestamp() AT TIME ZONE '<<DB Timezone>>';$BODY$LANGUAGE sql;在下面的代碼示例中,修改客戶(hù)端時(shí)區后也返回一致的結果:
CREATE OR REPLACE FUNCTION public.sysdate()RETURNS TIMESTAMP WITHOUT TIME ZONEAS$BODY$ SELECT clock_timestamp() AT TIME ZONE 'Europe/Berlin';$BODY$LANGUAGE sql; postgres=> set session time zone 'UTC';SETpostgres=> select sysdate(); sysdate---------------------------- 2020-01-03 07:34:54.441904(1 row) postgres=> set session time zone 'Asia/Kolkata';SETpostgres=> select sysdate(); sysdate---------------------------- 2020-01-03 07:35:02.392743(1 row)推薦下載:144頁(yè)!分享珍藏已久的數據庫技術(shù)年刊
數據和云
ID:OraNews
如有收獲,請劃至底部,點(diǎn)擊“在看”,謝謝!
聯(lián)系客服