2009-07-06 27 views
2

我在與其具有下述邏輯一個龐大的遺留PL/SQL程序問題:dbms_utility.get_time可以翻轉嗎?

l_elapsed := dbms_utility.get_time - l_timestamp; 

其中l_elapsedl_timestampPLS_INTEGER類型和l_timestamp的保持先前的呼叫的到get_time

結果

在批量運行期間,此行突然啓動失敗ORA-01426: numeric overflow

關於get_time的文檔有點含糊,可能故意這樣,但它的s強烈建議返回值沒有絕對的意義,並且可以是幾乎任何數字值。所以我很懷疑看到它被分配到一個PLS_INTEGER,它只能支持32位整數。然而,interweb充滿了人們正在做這種事情的例子。當調用get_time手動,它返回的-214512572的值,這是可疑接近一個32位帶符號整數的最小值

吸菸槍被發現。我想知道從第一次調用到get_time到第二次調用之間的時間間隔內,Oracle的內部計數器是否從最大值和最小值翻轉過來,導致在嘗試從另一箇中減去一個溢出時發生溢出。

這是一個可能的解釋嗎?如果是這樣,這是get_time函數的固有缺陷嗎?我可以等一下,看看批次今晚是否再次失敗,但我很想在此之前獲得對此行爲的解釋。

回答

2

10g doc

號碼的範圍是-2147483648回到2147483647取決於平臺和機器,你的應用程序必須採取數字的符號到在確定的時間間隔。例如,在兩個負數的情況下,應用程序邏輯必須允許第一個(較早的)數字大於第二個(較晚的)數字,它接近於零。同樣的道理,你的申請也應該允許第一個(較早)的數字是負數,第二個(後面的)數字是正數。

因此,儘管它是安全的dbms_utility.get_time結果分配給一個PLS_INTEGER這在理論上是可能的(但不太可能)您的批處理的執行過程中有一個溢出。這兩個值之間的差異將大於2^31。

如果您的工作需要大量時間(因此增加溢出發生的機率),您可能需要切換到TIMESTAMP數據類型。

+0

唉,真是一團糟。感謝您的澄清。我現在可以安心地休息,知道我可以等到DBA從假期中恢復過來,然後把地獄般的東西強加給他。 – skaffman 2009-07-06 10:54:37

0

分配一個負值,您PLS_INTEGER變量不引發ORA-01426:

SQL> l 
    1 declare 
    2 a pls_integer; 
    3 begin 
    4 a := -power(2,33); 
    5* end; 
SQL>/
declare 
* 
FOUT in regel 1: 
.ORA-01426: numeric overflow 
ORA-06512: at line 4 

但是,你似乎認爲-214512572接近-2^31,但它不是,除非你忘了以典型的數字。我們在看吸菸槍嗎?

Regards, Rob。

3

也許很晚,但這可能會有利於某人搜索同一問題。

底層實現是一個簡單的32位二進制計數器,從數據庫最後一次啓動開始,每隔100秒增加一次。

這個二進制計數器被映射到一個PL/SQL BINARY_INTEGER類型 - 這是一個有符號的32位整數(在64位機器上沒有改變爲64位的跡象)。

因此,假設時鐘從零開始,它將在大約248天后達到+ ve整數限制,然後翻轉成爲-ve值回落到零。

好消息是,如果兩個數字都是相同的符號,您可以做一個簡單的減法來找到持續時間 - 否則您可以使用32位餘數。

IF SIGN(:now) = SIGN(:then) THEN 
     RETURN :now - :then; 
    ELSE 
     RETURN MOD(:now - :then + POWER(2,32),POWER(2,32)); 
    END IF; 

編輯:此代碼將吹INT限制,如果時間之間的差距過大失敗(248天),但你不應該使用GET_TIME來比較天工期的措施反正(見下文) 。

最後 - 有一個問題,你爲什麼會使用GET_TIME。

從歷史上看,它是獲得亞秒級時間的唯一方法,但自引入SYSTIMESTAMP以來,唯一的原因就是使用GET_TIME的原因是速度很快 - 它是一個簡單的32位計數器映射,沒有真正的類型轉換,並且不會對底層OS時鐘函數產生任何影響(SYSTIMESTAMP似乎)。

由於它只是測量相對時間,所以它僅用於測量兩點之間的持續時間。對於需要大量時間的任何任務(您知道,超過千分之一秒左右),使用時間戳的代價是微不足道的。

實際上有用的場合的次數很少(我發現的唯一一個檢查緩存中的數據的年齡,每次訪問的時鐘命中時間變得很重要)。