在没有REGEXP_REPLACE和PL / SQL的情况下格式化UUID字符串

时间:2016-04-01 10:56:49

标签: string oracle format uuid

我希望格式化sys_guid()函数的结果,例如this answer中提出的

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

出于性能原因,我想避免使用regexp_replace(因为我处理大量记录)。

我的场景可以简化为这个用例:

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

显然,我不能使用substr和concatenation,因为每个SUBSTR都会处理不同的SYS_GUID。我还想留在SQL中,没有上下文切换到PL / SQL函数。

任何想法如何使用掩码格式化SQL中的字符串类似于日期或数字:

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

1 个答案:

答案 0 :(得分:4)

不幸的是,您不能在数字格式中包含字符串文字,否则您可以将十六进制字符串转换为数字然后再返回,在格式掩码中插入文字在正确的位置 - 但您只能这样做日期。

您可以使用substr(),因为这些位置是固定的。你担心的是

  

显然,我不能使用substr和concatenation,因为每个SUBSTR都会处理不同的SYS_GUID。

使用子查询因子分析(a.ka.一个公用表表达式/ CTE)意味着来自该CTE的行的substr()调用都看到相同的GUID;这种方法不会为每个生成一个新的SYS_GUID。

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    

比大量数据的正则表达式快得多。循环中有100000个值(在PL / SQL块中,在循环内执行最少量的工作以使其实际正确评估,并使用dbms_utility.get_cpu_time检查已用时间)正则表达式版本大约需要2.51秒,而子串版本大约需要0.29秒。您的系统当然会得到不同的数量,但它应该仍然大致相同的数量级。