2010-06-21 24 views
1

有沒有什麼辦法可以在Oracle 10g中將十進制轉換爲二進制或二進制轉換爲十進制而不必先定義一個函數?我有限的數據庫訪問(僅限SELECT),我在網上找到的所有解決方案似乎涉及CREATE FUNCTION,這對我不起作用。沒有函數的PL/SQL base轉換

回答

0

可以執行PL/SQL中的腳本的SQLPlus像這樣:

declare 
    procedure bin_2_dec(/*some parameters here*/) is 
    begin 
     /*do computation and print result*/ 
    end; 
begin  
    bin_2_dec('11110000'); 
end; 
/

我不知道,但我不認爲該函數將永久保存在數據庫中創建,我認爲它只會在劇本期間臨時存在,所以這可能工作。這值得一試,對吧? ;)

或者,如果這不起作用,你可以SELECT ... from dual轉換,雖然這可能會很尷尬,並且只會在你知道數字的位數時起作用 - 也許(如果我想把它放在一起可以得到幾分鐘,如果可能的話)。

+0

需要明確的是:我們不能在嵌入匿名塊的SQL語句中使用像這樣聲明的函數。這拋出了PLS-00231,因爲我們只能在SQL語句中使用SQL聲明的函數。 – APC 2010-06-21 16:00:31

+0

不,我想這個函數在SELET語句中是不可用的,但函數/過程*可以從SQLPlus腳本中的PL/SQL中使用*。我不知道腳本中的PL/SQL是否是可行的解決方案。 – FrustratedWithFormsDesigner 2010-06-21 16:05:42

2

如果十六進制足夠好,那麼TO_CHAR和TO_NUMBER可以工作:

SQL> select to_char(31, '0x') from dual; 

TO_ 
--- 
1f 

SQL> select to_number('1f', '0x') from dual; 

TO_NUMBER('1F','0X') 
-------------------- 
        31 

您可以使用RAWTOHEX()HEXTORAW()功能,使十六進制到二進制轉換爲好。

1

專門研究SQL疑難雜症的Frank Zhou爲此問題設計了一個純粹的SQL解決方案。你可以在his OraQA site找到它。但要注意的是:確實是粗糙。

更新

原文鏈接OraQA被打破:The Wayback Machine has an archived version here

+0

這確實是扭曲的。我喜歡。 ;) – FrustratedWithFormsDesigner 2010-06-21 20:05:47

+0

鏈接已死亡。解決方案可能與此相同 - https://asktom.oracle.com/pls/apex/f?p=100:11:::YES:RP:P11_QUESTION_ID:7041297073738 – jva 2016-03-10 13:35:33

+0

@jva - 感謝您的提示。我添加了一個存檔鏈接。 FZ解決方案比較複雜,因爲他不只是做十六進制。 – APC 2016-03-12 08:19:54

0

粗,但對於十進制到二進制直正解:

SELECT REPLACE 
     (REPLACE 
     (REPLACE 
     (REPLACE 
      (REPLACE 
      (REPLACE 
      (REPLACE 
      (REPLACE 
       (REPLACE 
       (REPLACE 
       (REPLACE 
       (REPLACE 
        (REPLACE 
        (REPLACE 
        (REPLACE 
        (REPLACE 
         (TO_CHAR (100,'FMxxx'), 
         '0','0000'), 
         '1','0001'), 
        '2','0010'), 
        '3','0011'), 
        '4','0100'), 
        '5','0101'), 
       '6','0110'), 
       '7','0111'), 
       '8','1000'), 
       '9','1001'), 
      'A','1010'), 
      'B','1011'), 
      'C','1100'), 
      'D','1101'), 
     'E','1110'), 
     'F','1111') 
    FROM DUAL; 

二進制到十進制將是棘手。您可以使用connect by將字符串拆分爲4個字符的分段,然後將它們以相似的方式進行轉換,然後將它們連接在一起(第二個connect by使用SYS_CONNECT_BY_PATH?),但這對我今晚的工作有些過於單調乏味。


關於第二個想法,這裏的二進制到十進制的解決方案(我爲connect by問題吸盤):

SELECT  TO_NUMBER(
       REPLACE (
        SYS_CONNECT_BY_PATH (octet, '!'), 
        '!', ''), 
       'xxxxxx') 
     FROM (SELECT  CASE SUBSTR 
           (LPAD (a, 
             CEIL (LENGTH(a)/4)*4, '0'), 
           (LEVEL-1)*4+1, 4) 
          WHEN '0000' 
          THEN '0' 
          WHEN '0001' 
          THEN '1' 
          WHEN '0010' 
          THEN '2' 
          WHEN '0011' 
          THEN '3' 
          WHEN '0100' 
          THEN '4' 
          WHEN '0101' 
          THEN '5' 
          WHEN '0110' 
          THEN '6' 
          WHEN '0111' 
          THEN '7' 
          WHEN '1000' 
          THEN '8' 
          WHEN '1001' 
          THEN '9' 
          WHEN '1010' 
          THEN 'A' 
          WHEN '1011' 
          THEN 'B' 
          WHEN '1100' 
          THEN 'C' 
          WHEN '1101' 
          THEN 'D' 
          WHEN '1110' 
          THEN 'E' 
          WHEN '1111' 
          THEN 'F' 
         END AS octet, 
         LEVEL AS seq, 
         CEIL (LENGTH(a)/4) AS max_level 
        FROM (SELECT '101010101010101010' AS a 
          FROM DUAL) 
      CONNECT BY LEVEL <= CEIL(LENGTH(a)/4)) 
    WHERE LEVEL = max_level 
CONNECT BY PRIOR seq = seq-1 

此解決方案僅適用於一行在作爲當前寫入時間。要使其與多行一起工作,您需要在最外面的connect by中添加某種唯一標識符。

+0

不錯的努力 - 很酷。 – 2014-02-06 05:12:42

0

我在Oracle中使用CONNECT BY在簡單的SELECT語句中將十進制轉換爲二進制。最後得到了期望的輸出。你可以使用下面,它工作正常。

WITH INPUT AS 
(SELECT &N AS X FROM DUAL) 
SELECT SUM(MOD(FLOOR(X*POWER(0.5,LEVEL-1)),2)*POWER(10,LEVEL-1)) AS 
OUTPUT FROM INPUT CONNECT BY POWER(2,LEVEL-1)<=X; 
相關問題