2010-04-02 12 views
13

Es ist eine Situation eingetreten, in der ich im Rahmen einer SQL-Anweisung eine Konvertierung von Base 36 zu Base 10 durchführen muss. Es scheint nichts in Oracle 9 oder Oracle 10 eingebaut zu sein, um solche Dinge anzugehen. Mein Google-Fu und AskTom schlagen vor, eine pl/sql-Funktion für die Aufgabe zu erstellen. Das ist für mich an dieser Stelle keine Option. Ich suche nach Vorschlägen für einen Ansatz, der mir helfen könnte, dieses Problem zu lösen.Umwandlung von Base 36 zu Base 10 nur mit SQL

Um dies in eine visuelle Form gebracht ...

WITH 
Base36Values AS 
(
    SELECT 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' myBase36 FROM DUAL 
), 
TestValues AS 
(
    SELECT '01Z' BASE36_VALUE, 
      71 BASE10_VALUE FROM DUAL 
) 
SELECT * 
FROM Base36Values, 
    TestValues 

ich nach etwas suchen, den Wert 71, basierend auf dem Eingang 01Z zu berechnen. BEARBEITEN - das ist rückwärts ... gegeben 01Z übersetze es zu 71.

Als Bestechung bekommt jede nützliche Antwort eine kostenlose Upvote.

Danke

Evil.

+1

Ich bin nur neugierig (Ich wollte immer eine Entschuldigung finden, um verschiedene Basen zu verwenden, um Daten zu speichern); Wofür werden die Basisdaten verwendet? –

+1

Und ich bin neugierig, warum dies in SQL getan werden muss, das ist nicht wirklich üblich. –

+3

Der Vorteil von Base 36 besteht darin, dass Sie ein eingebettetes Gerät verwenden können, das über eine begrenzte Tastatur verfügt, um Eingaben zu ermöglichen. Dann ist es aufgrund der Größe effizienter, sie als base36 anstatt als String zu interpretieren, und außerdem können Sie damit Standardfunktionen berechnen. – Henri

Antwort

22
select sum(position_value) from 
(
    select power(36,position-1) * case when digit between '0' and '9' 
            then to_number(digit) 
            else 10 + ascii(digit) - ascii('A') 
           end 
      as position_value 
    from (
      select substr(input_string,length(input_string)+1-level,1) digit, 
       level position 
      from (select '01Z' input_string from dual) 
      connect by level <= length(input_string) 
     ) 
) 
+0

+1, saweeeeeet! Hervorragende Illustration der Verwendung der Connect-by-Level-Syntax. – DCookie

+0

Ja. Ersetzen Sie die basis36-Zeichenfolge durch eine case-Anweisung. Danke Dave. – EvilTeach

2

Für T-SQL wird die folgende Logik die Aufgabe ausführen, die der obige Oracle-Code ausführt. Dies ist allgemeine allgemeine Lösung und Base-X zur Basis-10 unterstützen:

select 
    sum(power(base,pos-1) * 
      case when substring(cnv,pos,1) between '0' and '9' then 
       cast(substring(cnv,pos,1) as int) 
      else 10 + ascii(upper(substring(cnv,pos,1))) - ascii('A') end) 
    from (values(reverse('01Z'), 36)) as t(cnv,base) 
     left join (values(1),(2),(3),(4),(5),(6)) as x(pos) 
      on pos <= len(cnv) 

Um mit anderen Basen zu verwenden nur verwenden:

from (select cnv = reverse('FF'), base=16) as t 

oder

from (select cnv = reverse('101'), base=2) as t 

Beachten Sie, dass zur Unterstützung Zeichenfolgen, die länger als 6 sind, müssten Sie dem Positionsvektor mehr Werte hinzufügen.