我正在研究一些分析工具,我有一個特定的情況,我有一個使用 HEXTORAW Oracle 函式表示的值,如下所示:
HEXTORAW('7876031b0d233900786450')
該值表示否則將被寫為TO_TIMSTAMP('2018-03-27 12:34:56.00789')。到目前為止,我找到了兩種嘗試轉換此 HEXTORAW 值的方法:
- 使用
dbms_stats.convert_raw_to_date dbms_stats.convert_raw_value在 PL/SQL 塊中使用
在這兩種情況下,回傳值都沒有時間戳的分形秒部分,我懷疑這可能是由于底層呼叫依賴于DATE資料型別而不是真正的TIMESTAMP資料型別。
有誰知道是否有另一個 PL/SQL 包函式可用于將原始值解碼回包含分形秒的完整時間戳?
uj5u.com熱心網友回復:
沒有將十六進制字串轉換為 a 的函式,TIMESTAMP但您可以輕松計算該TIMESTAMP值。
將前 7 個位元組轉換為 a DATE,然后將其轉換為 a TIMESTAMP(9)(小數秒為 0),然后您可以將最后 4 個位元組轉換為一個數字,該數字表示納秒數,然后將其添加到時間戳中:
SELECT CAST(
DBMS_STATS.CONVERT_RAW_TO_DATE(HEXTORAW(SUBSTR(hex_value,1,14)))
AS TIMESTAMP(9)
)
INTERVAL '1' SECOND(9)
* TO_NUMBER(HEXTORAW(SUBSTR(hex_value,15,8)), 'XXXXXXXX') / 1e9
AS timestamp_val,
hex_value
FROM (
SELECT '7876031b0d233900786450' AS hex_value FROM DUAL
)
輸出:
TIMESTAMP_VAL HEX_VALUE 2018-03-27 12:34:56.007890000 7876031b0d233900786450
和
CREATE TABLE table_name (value TIMESTAMP(9));
INSERT INTO table_name (value) VALUES (TIMESTAMP '2018-03-27 12:34:56.007890000');
SELECT value, DUMP(value,16) FROM table_name
輸出:
價值 轉儲(值,16) 2018-03-27 12:34:56.007890000 Typ=180 Len=11: 78,76,3,1b,d,23,39,0,78,64,50
它具有相同的時間戳和相同的位元組值。
如果你想把它包裝成一個函式,那么:
CREATE FUNCTION hex_to_timestamp(
hex_value IN VARCHAR2
) RETURN TIMESTAMP DETERMINISTIC
IS
BEGIN
RETURN CAST(
DBMS_STATS.CONVERT_RAW_TO_DATE(HEXTORAW(SUBSTR(hex_value,1,14)))
AS TIMESTAMP
)
INTERVAL '1' SECOND
* TO_NUMBER(HEXTORAW(SUBSTR(hex_value,15,8)), 'XXXXXXXX') / 1e9;
END;
/
db<>在這里擺弄
更新
也許“最簡單”的方法是使用已經將位元組字串轉換為時間戳的東西。在這種情況下,Java 類oracle.sql.TIMESTAMP有一個建構式,它接受一個位元組陣列(并且有一個類似的建構式oracle.sql.TIMESTAMPTZ)。
因此,如果您在資料庫中啟用了 Java,則可以使用一個小類將十六進制字串轉換為位元組陣列,然后將建構式包裝在函式中:
CREATE AND COMPILE JAVA SOURCE NAMED HexToTimestampConverter AS
import oracle.sql.TIMESTAMP;
import oracle.sql.TIMESTAMPTZ;
public class HexToTimestampConverter {
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i = 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
Character.digit(s.charAt(i 1), 16));
}
return data;
}
public static TIMESTAMP hexToTimestamp(final String hex)
{
return new TIMESTAMP(hexStringToByteArray(hex));
}
public static TIMESTAMPTZ hexToTimestamptz(final String hex)
{
return new TIMESTAMPTZ(hexStringToByteArray(hex));
}
}
然后您可以創建一個 SQL 函式來呼叫 Java 代碼:
CREATE FUNCTION hex_to_timestamp( in_value IN VARCHAR2 ) RETURN TIMESTAMP
AS LANGUAGE JAVA NAME 'HexToTimestampConverter.hexToTimestamp(java.lang.String) return oracle.sql.TIMESTAMP';
/
對于TIMESTAMP WITH TIME ZONE:
CREATE FUNCTION hex_to_timestamptz( in_value IN VARCHAR2 ) RETURN TIMESTAMP WITH TIME ZONE
AS LANGUAGE JAVA NAME 'HexToTimestampConverter.hexToTimestamptz(java.lang.String) return oracle.sql.TIMESTAMPTZ';
/
(注意:您可能需要添加一些錯誤檢查來檢查字串是否為十六進制且長度正確。)
db<>在這里擺弄
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/489459.html
上一篇:根據日期欄位獲取活動行
