TL;DR: in Oracle 26ai, there is the new function UUID(), which implements the UUID-V4. Someone also mentioned UUID-V7. I started experimenting with the Possibilities.
And of course I expect (hope) Oracle implements other versions of UUID quite soon...
(For the purists on Standards and Database-IDs, keys: Several Caveats included. Dont do this in Production unless You Know What You are Doing...)
Image: some Universe with the UUID.
Background: UUID are everywhere (but I avoided them)
So far, I have not encountered UUIDs much in Oracle. Some other databases use UUID, and to me it was mostly a funny-looking random-string. I was aware of the Benefits of UUIDs: Uniqueness + Randomness, even when generated at different place and time. And in Oracle there was the SYS_GUID() function, should we need it. But I dont think I ever used it.
That May Change: Because in Oracle 26ai, there is a function to generate UUID-V4 keys.
Here is the link to the Standard Paper (which I didnt Study in Detail myself...)
Jonathan Lewis experimented some, he also dug into the error-messages, and pointed out that Oracle will probably also implements the versions 1, 2, 3, 7, and 8 (link to forum)
In the Database-world, the growing consensus seems to be that UUID-V7 is Better. Notably in this article is an interesting example of someone who tried to benchmark, and concluded that "in his case" the UUID-V7 was better in a number of scenarios.
We also had at least 1 Oracle-DBA who was Actively Asking for UUID-V7. And as Jonathan Lewis showed, the indications are that this will be implemented at some point in the (near) future.
Let's write some code...
DBA's being Data-Geeks. Shortly after the intro of UUID-V4 in Oracle came the discussion whether UUID-V4 was good, was usable, or was just plain bad for use (as a key/reference/pointer) in an Oracle RDBMS.
Link(s) to script(s) are at bottom of blog, in case someone wants to mess with it.
Raw, but (not very) Readable...
The Basis if the UUIDs is a 128-bit number, and this wiki-page on UUIDs is quite extensive.
Given the definition of the standard, and the nature of the documentation found so far, the consensus between myself and a small group was: Store this as RAW(16) for the moment (we might re-consider that later, and of course ymmv...).
With a copy of the code from Jasmin, I was able quicly able to create UUIDs of V7.
For the complete source: link at bottom.
I was now able to create UUID-V7 and experiment with them.
From working with "the other database", I was used to see UUIDs in a certain format. And I sometimes had data-sets delivered to me with (quoted) GUID-keys in them. They are generally displayed as 8-4-4-4-12, as per Standard. Both the Standard and the Wiki-page also states that the Lowercase is preferred.
At this point I regretted that Oracle did not have (yet) a data-type for UUID. In the other database, I can define a column as a UUID, and get the display-formatting automatically on selecting the column.
Oracle provides the function RAW_TO_UUID, but at this moment, Oct 2025, with v23.26ai, that only works on UUID-V4 keys.
So out of habit, I wrote a formatting-function to facilitate display of generic UUIDs. The result was :
As we can see, the function is able too format most forms of UUID, including the old SYS-GUID() from Oracle v12.x. Can you spot the V4 and V7 UUIDs?
Time-ordered keys, hence I want Boundaries, Ranges.
The UUID-V7 is specifically time-ordered. That means that if you use them in an ORDER-BY, that the values are sorted by "created_date".
Thus, if I wanted to select all the records with UUID-V7 keys generated between T1 and T2, I needed to be able to specify T1 and T2, Precisely, and in a RAW, UUID usable type.
This called for a function that would generate the UUID7 for a Given Timestamp. The result was :
By specifying a timestamp, I obtain the corresponding UUID. And I placed some irrelevant (?), but informative data in the "random bytes" after the last two groups.
Caveat - Note: I ignored the "variant" information from the Standard-spec. Something to think about later.
The results, output, can look like this :
The first two lines in the result are the UUID generated with explicitly-specified SYSDATE and SYSTIMESTAMP. And the time is "readably" stored in the last two groups of 4 + 12 bytes. You can recognise the ID generated from SYSDATE in the first record from the last two bytes: Because the DATE is only accurate to the Seconds, the Centi-Seconds, are "00".
You can experiment for yourself with the peculiar difference between :
Select uuid7_ts ( systimestamp) from dual connect by level < 3;
Select uuid7_ts ( ) from dual connect by level < 3;
There might be discussion on the implementation-possibilties there... Later.
Main point is: I can now filter the UUIDs generated before, after or between timestamps.
Caveat! ... This is Not Best Practice (abuse of "information" in key-fields).. But it can bed Very Useful when analyzing data per hour / day / week.
Closing Summary (hmmm, not yet closing...).
It looks like we can now generate UUID-V7 values. And we can even generate them with "given timestamps".
We have the following functions:
- FMT_UUID ( UUID ) : return a varchar2 with uuid-format: 8-4-4-4-12 for "display" usage. For formatting the other UUIDs, since Oracle choose to accept only UUID-V4 for their RAW_TO_UUID (), at this moment (Oct 2025).
- UUID7 () : return a RAW(16) with the UUID of V7
- UUID7_TS ( Some_TS ) : return a RAW(16) with a UUID-V7, but with the time-part set to the given parameter.
I look forward to playing with those ...
Because there is More...
Now, Once we have the ability to generate "precisely timed values", we can use those to allow partitioning on Time-ranges. Something for another session.
Then there is the question: Do I want to Know the Time ? The UUIDs of type V1, V6 and V7 contain timestamp-bits. I can potentially extract the time-of-generation from those. Would this be useful?
For a future versions, I would also consider creating a package to bundle all my UUID-related functions. A package will also allow "overloading" the two functions UUID7() and UUID7_TS() to a single "name". Something to think about.
Give me some time to think and experiment...
Or.. You can experiment Yourself.
The best learning is from the things You Do Yourself - so Go tweak this code.
Enjoy !
-- -- -- -- -- -- End of blog text, for now -- -- -- -- -- --
Appendix A : links to Scripts..
mk_uuid7.sql : create the functions, and some test code to verify.
demo_uuid_fmt : demo the formatting.
-- -- -- -- -- -- end of this blog-episode, for real -- -- -- -- -- --







No comments:
Post a Comment