格式化没有 REGEXP_REPLACE 和 PL/SQL 的 UUID 字符串
Formating UUID String without REGEXP_REPLACE and PL/SQL
我想按照 this answer
中的建议格式化 sys_guid() 函数的结果
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})'
, '----')
as FORMATTED_GUID
from dual
出于性能原因,我想避免使用 regexp_replace(因为我要处理大量记录)。
我的场景可以简化为这个用例:
select rawtohex(sys_guid()) GUID
from dual connect by level <= 2;
显然我不能使用 substr 和串联,因为每个 SUBSTR 会处理不同的 SYS_GUID。我还想留在 SQL,无需上下文切换到 PL/SQL 函数。
知道如何使用掩码将 SQL 中的字符串格式化为类似于日期或数字的格式:
to_char(rawtohex(sys_guid(),'CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC') /* note, this is clear illegal */
不幸的是,您不能在数字格式中包含字符串文字,否则您可以将十六进制字符串转换为数字然后再转换回来,在格式掩码中的正确位置插入文字 - 但您只能这样做日期。
你可以使用substr()
,因为位置是固定的。你担心
Obviously I can't use substr and concatenation as each SUBSTR would process a different SYS_GUID.
使用子查询分解(a.ka。常见的 table expression/CTE)意味着 substr()
调用来自该 CTE 的行都看到相同的 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 秒。你的系统当然会得到不同的数字,但它应该仍然是大约相同的数量级。
我想按照 this answer
中的建议格式化 sys_guid() 函数的结果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})'
, '----')
as FORMATTED_GUID
from dual
出于性能原因,我想避免使用 regexp_replace(因为我要处理大量记录)。
我的场景可以简化为这个用例:
select rawtohex(sys_guid()) GUID
from dual connect by level <= 2;
显然我不能使用 substr 和串联,因为每个 SUBSTR 会处理不同的 SYS_GUID。我还想留在 SQL,无需上下文切换到 PL/SQL 函数。
知道如何使用掩码将 SQL 中的字符串格式化为类似于日期或数字的格式:
to_char(rawtohex(sys_guid(),'CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC') /* note, this is clear illegal */
不幸的是,您不能在数字格式中包含字符串文字,否则您可以将十六进制字符串转换为数字然后再转换回来,在格式掩码中的正确位置插入文字 - 但您只能这样做日期。
你可以使用substr()
,因为位置是固定的。你担心
Obviously I can't use substr and concatenation as each SUBSTR would process a different SYS_GUID.
使用子查询分解(a.ka。常见的 table expression/CTE)意味着 substr()
调用来自该 CTE 的行都看到相同的 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 秒。你的系统当然会得到不同的数字,但它应该仍然是大约相同的数量级。