2016-04-01 4 views
2

Ich mag würde das Ergebnis der sys_guid() Funktion zu formatieren wie in this answerFormating String ohne REGEXP_REPLACE und PL/SQL

select regexp_replace(rawtohex(sys_guid()) 
     , '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})' 
     , '\1-\2-\3-\4-\5') 
     as FORMATTED_GUID 
from dual 

Aus Performance-Gründen vorgeschlagen würde Ich mag die Verwendung von REGEXP_REPLACE vermeiden (da ich eine große Anzahl von Datensätzen verarbeite).

Mein Szenario zu diesem Anwendungsfall vereinfacht werden:

select rawtohex(sys_guid()) GUID 
from dual connect by level <= 2; 

Offensichtlich ich nicht substr und Verkettung als jeder SUBSTR eine andere SYS_GUID würde verarbeiten können. Ich möchte auch in SQL bleiben, ohne einen Kontextwechsel auf PL/SQL-Funktion.

Jede Idee, wie Zeichenfolge in SQL eine Maske ähnlich wie Datum oder zu formatieren, mit:

to_char(rawtohex(sys_guid(),'CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC') /* not this is clear illegal */ 

Antwort

4

Sie nicht Stringliterale in Nummer leider Formate enthalten können, sonst könnten Sie die Hex-String in eine Zahl umwandeln und dann wieder zurück, Einfügen von Literalen in die Formatmaske an den richtigen Stellen - aber das können Sie nur für Daten tun.

Sie können substr() verwenden, da die Positionen festgelegt sind. Sie waren besorgt, dass

Offensichtlich kann ich substr und Verkettung nicht verwenden, da jeder SUBSTR eine andere SYS_GUID verarbeiten würde.

Unterabfrage factoring Unter Verwendung von (a.ka. einer gemeinsamen Tabelle Expressions-/CTE) bedeutet die substr() Anrufe für eine Zeile von dem CTE alle die gleiche GUID sehen; Diese Methode generiert keine neue SYS_GUID für jede einzelne.

with t as (
    select rawtohex(sys_guid()) guid from dual 
    connect by level <= 2 
) 
select guid, substr(guid, 1, 8) 
    ||'-'|| substr(guid, 9, 4) 
    ||'-'|| substr(guid, 13, 4) 
    ||'-'|| substr(guid, 17, 4) 
    ||'-'|| substr(guid, 21, 12) as formatted_guid 
from t; 

GUID        FORMATTED_GUID       
-------------------------------- ---------------------------------------- 
2F6BA62518F926D0E0534D49E50ABB46 2F6BA625-18F9-26D0-E053-4D49E50ABB46  
2F6BA62518FA26D0E0534D49E50ABB46 2F6BA625-18FA-26D0-E053-4D49E50ABB46  

Das ist viel schneller als die Regex auf eine größere Datenmenge. Bei 100000 Werten in einer Schleife (in einem PL/SQL-Block, die nur eine minimale Menge an Arbeit innerhalb der Schleife ausführt, um eine korrekte Auswertung zu ermöglichen und die abgelaufene Zeit mit dbms_utility.get_cpu_time zu überprüfen) dauert die Regex-Version etwa 2,51 Sekunden Version dauert etwa 0,29 Sekunden. Ihr System wird natürlich unterschiedliche Zahlen erhalten, aber es sollte immer in der gleichen Größenordnung liegen.