zoukankan      html  css  js  c++  java
  • TIMESTAMPN(N) WITH LOCAL TIMEZONE数据类型转换

    --TYPE#=231为TIMESTAMP(N) WITH LOCAL TIME ZONE,181为TIMESTAMP(N) WITH TIME ZONE
    select u.name || '.' || o.name || '.' || c.name TSLTZcolumn
    from sys.obj$ o, sys.col$ c, sys.user$ u
    where c.type#=231 and o.obj#=c.obj# and u.user#=o.owner#;
    ------------------------------------
    --某时区和 UTC 之间的差值
    SELECT TZ_OFFSET('US/Eastern') FROM DUAL;
    SELECT TZ_OFFSET(DBTIMEZONE) FROM DUAL;
    SELECT TZ_OFFSET(SESSIONTIMEZONE) FROM DUAL;
    SELECT TZ_OFFSET('-11:11') FROM DUAL
    --数据库时区
    SELECT DBTIMEZONE FROM DUAL;
    --会话时区
    SELECT SESSIONTIMEZONE FROM DUAL;
    ------------------------------------
    --TIMESTAMP(N) WITH TIME ZONE TIMESTAMP(N) WITH LOCAL TIME ZONE 存储格式及引擎 sql引擎
    --TO_TIMESTAMP_TZ函数 时的12和24进度 最小精度为纳秒
    --AM/PM都可以转换得到下午,此时HH12为12进度(由上午、下午和格式中的AM/PM限制)且此时可以忽略TZR时区格式而只指定AM/PM
    --TO_TIMESTAMP_TZ得到的数据类型用TO_CHAR转换时,12和24进度都可以指定AM/PM格式,反之只有12进度可以指定
    --不含时区 12进度 得到默认时区 必须写上午和下午否则只能得到上午的值
    SELECT TO_TIMESTAMP_TZ(TO_CHAR(TO_TIMESTAMP_TZ('2018-01-01 11:11:11.111222333 下午','YYYY-MM-DD HH12:MI:SS.FF9 AM TZR'),'YYYY-MM-DD HH12:MI:SS.FF9 AM TZR'),'YYYY-MM-DD HH12:MI:SS.FF9 AM TZR') FROM DUAL;
    SELECT TO_TIMESTAMP_TZ(TO_CHAR(TO_TIMESTAMP_TZ('2018-01-01 11:11:11.111222333 下午','YYYY-MM-DD HH12:MI:SS.FF9 PM TZR'),'YYYY-MM-DD HH12:MI:SS.FF9 PM TZR'),'YYYY-MM-DD HH12:MI:SS.FF9 PM TZR') FROM DUAL;
    --含时区 12进度 得到存储时区 必须写上午和下午否则只能得到上午的值
    SELECT TO_TIMESTAMP_TZ(TO_CHAR(TO_TIMESTAMP_TZ('2018-01-01 11:11:11.111222333 下午 +01:00','YYYY-MM-DD HH12:MI:SS.FF9 AM TZR'),'YYYY-MM-DD HH12:MI:SS.FF9 AM TZR'),'YYYY-MM-DD HH12:MI:SS.FF9 AM TZR') FROM DUAL;
    SELECT TO_TIMESTAMP_TZ(TO_CHAR(TO_TIMESTAMP_TZ('2018-01-01 11:11:11.111222333 下午 +01:00','YYYY-MM-DD HH12:MI:SS.FF9 PM TZR'),'YYYY-MM-DD HH12:MI:SS.FF9 PM TZR'),'YYYY-MM-DD HH12:MI:SS.FF9 PM TZR') FROM DUAL;

    --24进度(转换格式中不需要指定对应12进度的AM/PM),自动转换出上午、下午和时区
    SELECT TO_TIMESTAMP_TZ(TO_CHAR(TO_TIMESTAMP_TZ('2018-01-01 22:11:11.111222333','YYYY-MM-DD HH24:MI:SS.FF9 TZR'),'YYYY-MM-DD HH24:MI:SS.FF9 TZR'),'YYYY-MM-DD HH24:MI:SS.FF9 TZR') FROM DUAL;
    --24进度(转换格式中不需要指定对应12进度的AM/PM),自动转换出上午、下午和指定的时区
    SELECT TO_TIMESTAMP_TZ(TO_CHAR(TO_TIMESTAMP_TZ('2018-01-01 22:11:11.111222333 +01:00','YYYY-MM-DD HH24:MI:SS.FF9 TZR'),'YYYY-MM-DD HH24:MI:SS.FF9 TZR'),'YYYY-MM-DD HH24:MI:SS.FF9 TZR') FROM DUAL;
    -------------------------------------
    --若转换与存储引擎中存储格式一致的数据(若数据库的sql引擎支持TO_CHAR且不指定格式,因为转化格式无中文的匹配模式),若不指定格式但数据库sql引擎支持此写法则可以这么些
    SELECT TO_TIMESTAMP_TZ(TO_CHAR(TO_TIMESTAMP_TZ('01-1月-18 11:11:11.111222333 下午 +01:00'))),TO_TIMESTAMP_TZ('01-1月-18 11:11:11.111222333 下午 +01:00') FROM DUAL;
    SELECT TO_TIMESTAMP_TZ(TO_CHAR(TO_TIMESTAMP_TZ('01-1月-18 11:11:11.111222333 下午'))),TO_TIMESTAMP_TZ('01-1月-18 11:11:11.111222333 下午') FROM DUAL;
    -------------------------------------
    --开发案例,TO_CHAR后拼接得到时区差的TIMESTAMP(N) WITH LOCAL TIME ZONE数据类型的session(模拟时区)对应值
    --亚秒级的精度丢失解决方案 最小精度为纳秒
    SELECT SESSIONTIMEZONE,DBTIMEZONE,SYSTIMESTAMP,
    SYSTIMESTAMP+(SUBSTR(SESSIONTIMEZONE,2,2)+SUBSTR(SESSIONTIMEZONE,5,2)/60-SUBSTR(DBTIMEZONE,2,2)-SUBSTR(DBTIMEZONE,2,2)/60)/24 FROM DUAL;
    --逻辑
    SELECT SYSTIMESTAMP,
    TO_TIMESTAMP_TZ(TO_CHAR(SYSTIMESTAMP+SUBSTR(SESSIONTIMEZONE,2,2)/24+SUBSTR(SESSIONTIMEZONE,5,2)/24/60-SUBSTR(DBTIMEZONE,2,2)/24-SUBSTR(DBTIMEZONE,5,2)/24/60,'YYYY-MM-DD HH24:MI:SS')||SUBSTR(TO_CHAR(SYSTIMESTAMP,'YYYY-MM-DD HH24:MI:SS.FF6 TZR'),20),'YYYY-MM-DD HH24:MI:SS.FF6 TZR') FROM DUAL;

    --CREATE TABLE
    DROP TABLE VI.A34;

    CREATE TABLE A34 (
    ID NUMBER,
    NAME VARCHAR2(200) DEFAULT 'ABC' NOT NULL,
    V_TIMESTAMP_N TIMESTAMP(9) WITH TIME ZONE DEFAULT TO_TIMESTAMP('2018-01-01 10:10:10.111222333','YYYY-MM-DD HH24:MI:SS.FF9') NOT NULL,
    V_TIMESTAMP_LOCAL TIMESTAMP(9) WITH LOCAL TIME ZONE DEFAULT TO_TIMESTAMP('2018-01-01 10:10:10.111222333','YYYY-MM-DD HH24:MI:SS.FF9') NOT NULL
    );
    ALTER TABLE A34 ADD CONSTRAINT PK_A34 PRIMARY KEY(ID);

    --写入的TIMESTAMP(N) WITH LOCAL TIME ZONE数据类型数据保持不变
    DECLARE
    V_SESSIONTIME_SET VARCHAR2(200);
    BEGIN
    V_SESSIONTIME_SET:='''+'||LPAD(TO_CHAR(TO_NUMBER(SUBSTR(DBTIMEZONE,2,2)+0)),2,0)||':'||LPAD(TO_CHAR(TO_NUMBER(SUBSTR(DBTIMEZONE,5,2))+0),2,0)||'''';
    DBMS_OUTPUT.put_line(V_SESSIONTIME_SET);
    EXECUTE IMMEDIATE 'ALTER SESSION SET TIME_ZONE='||V_SESSIONTIME_SET;
    END;
    /

    DELETE FROM VI.A34;
    INSERT INTO A34(ID,NAME) SELECT 1,'AB1' FROM DUAL;
    INSERT INTO A34(ID,NAME) SELECT 2,'AB2' FROM DUAL;
    INSERT INTO A34(ID,NAME) SELECT 3,'AB3' FROM DUAL;
    COMMIT;

    SELECT SESSIONTIMEZONE,DBTIMEZONE,SYSDATE,T.* FROM VI.A34 T;

    --CREATE FUUNCTION
    --不启用RESULT_CACHE,若启用则结果集缓存与参数一一对应
    --用于客户端查询,转换结果返回TO_TIMESTAMP的数据类型
    CREATE OR REPLACE FUNCTION GET_TS_TZ_INC_CLIENT(
    V_OWNER VARCHAR2,
    V_TABLE_NAME VARCHAR2,
    V_COL_NAME VARCHAR2,
    V_INPUT VARCHAR2
    )
    RETURN VARCHAR2 /*RESULT_CACHE*/ AS
    PRAGMA AUTONOMOUS_TRANSACTION;
    N_DATA_SCALE NUMBER;
    V_SQL_EXE_TEMP VARCHAR2(1000);
    BEGIN
    BEGIN
    SELECT T.DATA_SCALE INTO N_DATA_SCALE FROM DBA_TAB_COLUMNS T WHERE T.OWNER=V_OWNER AND T.TABLE_NAME=V_TABLE_NAME AND T.COLUMN_NAME=V_COL_NAME;
    SELECT
    'TO_TIMESTAMP(TO_CHAR('||'TO_TIMESTAMP('||'SUBSTR('||V_INPUT||',1,20+'||N_DATA_SCALE||')'||',''YYYY-MM-DD HH24:MI:SS.FF'||N_DATA_SCALE||''')'||'+(SUBSTR('||'SESSIONTIMEZONE'||',2,2)+SUBSTR('||'SESSIONTIMEZONE'||',5,2)/60-SUBSTR('||'DBTIMEZONE'||',2,2)-SUBSTR('||'DBTIMEZONE'||',2,2)/60)/24,''YYYY-MM-DD HH24:MI:SS'')
    ||SUBSTR('||V_INPUT||',20,20+'||N_DATA_SCALE||'),''YYYY-MM-DD HH24:MI:SS.FF'||N_DATA_SCALE||''')'
    INTO V_SQL_EXE_TEMP
    FROM DUAL;
    EXCEPTION WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(SQLCODE||'--'||SQLERRM||':'||CHR(10)||V_SQL_EXE_TEMP);
    RAISE_APPLICATION_ERROR(-20010,SQLCODE||'--'||SQLERRM||':'||CHR(10)||V_SQL_EXE_TEMP);
    END;
    RETURN V_SQL_EXE_TEMP;
    END GET_TS_TZ_INC_CLIENT;
    /

    --用于服务端查询,转换结果返回TO_CHAR的数据类型
    CREATE OR REPLACE FUNCTION GET_TS_TZ_INC_SERVER(
    V_OWNER VARCHAR2,
    V_TABLE_NAME VARCHAR2,
    V_COL_NAME VARCHAR2,
    V_INPUT VARCHAR2
    )
    RETURN VARCHAR2 /*RESULT_CACHE*/ AS
    PRAGMA AUTONOMOUS_TRANSACTION;
    N_DATA_SCALE NUMBER;
    V_SQL_EXE_TEMP VARCHAR2(1000);
    BEGIN
    BEGIN
    SELECT T.DATA_SCALE INTO N_DATA_SCALE FROM DBA_TAB_COLUMNS T WHERE T.OWNER=V_OWNER AND T.TABLE_NAME=V_TABLE_NAME AND T.COLUMN_NAME=V_COL_NAME;
    SELECT
    'TO_CHAR('||'TO_TIMESTAMP('||'SUBSTR('||V_INPUT||',1,20+'||N_DATA_SCALE||')'||',''YYYY-MM-DD HH24:MI:SS.FF'||N_DATA_SCALE||''')'||'+(SUBSTR('||'DBTIMEZONE'||',2,2)+SUBSTR('||'DBTIMEZONE'||',5,2)/60-SUBSTR('||'SESSIONTIMEZONE'||',2,2)-SUBSTR('||'SESSIONTIMEZONE'||',5,2)/60)/24,''YYYY-MM-DD HH24:MI:SS'')
    ||SUBSTR('||V_INPUT||',20,20+'||N_DATA_SCALE||')'
    INTO V_SQL_EXE_TEMP
    FROM DUAL;
    EXCEPTION WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(SQLCODE||'--'||SQLERRM||':'||CHR(10)||V_SQL_EXE_TEMP);
    RAISE_APPLICATION_ERROR(-20010,SQLCODE||'--'||SQLERRM||':'||CHR(10)||V_SQL_EXE_TEMP);
    END;
    RETURN V_SQL_EXE_TEMP;
    END GET_TS_TZ_INC_SERVER;
    /

    --验证函数
    select SESSIONTIMEZONE,DBTIMEZONE,T.* from a34 t;
    select get_ts_tz_inc_client('VI','A34','V_TIMESTAMP_LOCAL','''2018-01-01 12:12:12.111222999''') from dual;
    select get_ts_tz_inc_SERVER('VI','A34','V_TIMESTAMP_LOCAL','''2018-01-01 12:12:12.111222999''') from dual;

    --SCRIPT TEST
    --CLIENT READ
    SELECT * FROM VI.A34 T;

    SELECT SESSIONTIMEZONE,DBTIMEZONE,'''+'||LPAD(TO_CHAR(TO_NUMBER(SUBSTR(DBTIMEZONE,2,2)+1)),2,0)||':'||LPAD(TO_CHAR(TO_NUMBER(SUBSTR(DBTIMEZONE,5,2))+10),2,0)||'''' FROM DUAL;
    --动态sql不能再ddl中赋值更新
    --ALTER SESSION SET TIME_ZONE='+'||LPAD(TO_CHAR(TO_NUMBER(SUBSTR(DBTIMEZONE,2,2)+1)),2,0)||':'||LPAD(TO_CHAR(TO_NUMBER(SUBSTR(DBTIMEZONE,5,2))+10),2,0)||'';
    --ALTER SESSION SET TIME_ZONE='+01:10'

    DECLARE
    V_SESSIONTIME_SET VARCHAR2(200);
    BEGIN
    V_SESSIONTIME_SET:='''+'||LPAD(TO_CHAR(TO_NUMBER(SUBSTR(DBTIMEZONE,2,2)+1)),2,0)||':'||LPAD(TO_CHAR(TO_NUMBER(SUBSTR(DBTIMEZONE,5,2))+10),2,0)||'''';
    DBMS_OUTPUT.put_line(V_SESSIONTIME_SET);
    EXECUTE IMMEDIATE 'ALTER SESSION SET TIME_ZONE='||V_SESSIONTIME_SET;
    END;
    /

    SELECT VI.GET_TS_TZ_INC_CLIENT('VI','A34','T_TIMESTAMP') FROM DUAL;

    SELECT SESSIONTIMEZONE,DBTIMEZONE,T.T_TIMESTAMP,
    TO_TIMESTAMP_TZ(TO_CHAR(T_TIMESTAMP+(SUBSTR('+01:10',2,2)+SUBSTR('+01:10',5,2)/60-SUBSTR('+00:00',2,2)-SUBSTR('+00:00',2,2)/60)/24,'YYYY-MM-DD HH24:MI:SS')
    ||SUBSTR(TO_CHAR(T_TIMESTAMP,'YYYY-MM-DD HH24:MI:SS.FF9 TZR'),20),'YYYY-MM-DD HH24:MI:SS.FF9 TZR')
    FROM VI.A34 T;

    -------------
    --SERVER WRITE 输入参数为把TIMESTAMP(N)转换为VARCHAR2
    SELECT VI.GET_TS_TZ_INC_SERVER('VI','A34','T_TIMESTAMP','2018-01-01 10:10:10.111222333') FROM DUAL;

    SELECT SESSIONTIMEZONE,DBTIMEZONE,TO_TIMESTAMP('2018-01-01 10:10:10.111222333','YYYY-MM-DD HH24:MI:SS.FF9') AS TO_TIMESTAMP_COMPARE,
    TO_TIMESTAMP_TZ(TO_CHAR(TO_TIMESTAMP('2018-01-01 10:10:10.111222333','YYYY-MM-DD HH24:MI:SS.FF9')+(SUBSTR('+00:00',2,2)+SUBSTR('+00:00',5,2)/60-SUBSTR('+01:10',2,2)-SUBSTR('+01:10',5,2)/60)/24,'YYYY-MM-DD HH24:MI:SS')
    ||SUBSTR(TO_CHAR(TO_TIMESTAMP('2018-01-01 10:10:10.111222333','YYYY-MM-DD HH24:MI:SS.FF9'),'YYYY-MM-DD HH24:MI:SS.FF9 TZR'),20),'YYYY-MM-DD HH24:MI:SS.FF9 TZR')
    FROM DUAL;

    -以下为拓展部分,当结果集缓存不完全依赖于参数时的风险需要消除
    --DETERMINISTIC FUNCTION 确定性参数结果集函数
    CREATE OR REPLACE FUNCTION GET_TIMESTAMP_N(
    N_ID NUMBER
    )
    RETURN VARCHAR2 DETERMINISTIC/*RESULT_CACHE*/ AS
    PRAGMA AUTONOMOUS_TRANSACTION;
    V_NAME VARCHAR2(40);
    BEGIN
    SELECT T.NAME INTO V_NAME FROM VI.A34 T WHERE T.ID=N_ID;
    RETURN V_NAME;
    END GET_TIMESTAMP_N;
    /

    --RESULT_CACHE FUNCTION 结果集缓存函数
    CREATE OR REPLACE FUNCTION GET_TIMESTAMP_N(
    N_ID NUMBER
    )
    RETURN VARCHAR2 RESULT_CACHE AS
    PRAGMA AUTONOMOUS_TRANSACTION;
    V_NAME VARCHAR2(40);
    BEGIN
    SELECT T.NAME INTO V_NAME FROM VI.A34 T WHERE T.ID=N_ID;
    RETURN V_NAME;
    END GET_TIMESTAMP_N;
    /

  • 相关阅读:
    现代软件工程 第一章 概论 第3题——韩婧
    现代软件工程 第一章 概论 第2题——韩婧
    小组成员邓琨、白文俊、张星星、韩婧
    UVa 10892 LCM的个数 (GCD和LCM 质因数分解)
    UVa 10780 幂和阶乘 求n!中某个因子的个数
    UVa 11859 除法游戏(Nim游戏,质因子)
    Codeforces 703C Chris and Road 二分、思考
    Codeforces 703D Mishka and Interesting sum 树状数组
    hdu 5795 A Simple Nim SG函数(多校)
    hdu 5793 A Boring Question 推公式(多校)
  • 原文地址:https://www.cnblogs.com/buffercache/p/10071919.html
Copyright © 2011-2022 走看看