Last active
February 14, 2025 17:46
-
-
Save fabiolimace/e3c3d354d1afe0b3175f65be2d962523 to your computer and use it in GitHub Desktop.
UUIDv7 for SQLite using view and triggers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DROP VIEW IF EXISTS uuid7; | |
CREATE VIEW uuid7 AS | |
WITH unixtime AS ( | |
SELECT CAST((STRFTIME('%s') * 1000) + ((STRFTIME('%f') * 1000) % 1000) AS INTEGER) AS time | |
-- SELECT CAST((UNIXEPOCH('subsec') * 1000) AS INTEGER) AS time -- for SQLite v3.38.0 (2022) | |
) | |
SELECT PRINTF('%08x-%04x-%04x-%04x-%012x', | |
(select time from unixtime) >> 16, | |
(select time from unixtime) & 0xffff, | |
ABS(RANDOM()) % 0x0fff + 0x7000, | |
ABS(RANDOM()) % 0x3fff + 0x8000, | |
ABS(RANDOM()) >> 16) AS next; | |
-- EXAMPLE: | |
-- | |
-- sqlite> SELECT next FROM uuid7; | |
-- 01901973-f202-71ca-9a22-14e7146dab85 | |
-- | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- DROP TABLE IF EXISTS my_table; | |
CREATE TABLE my_table ( | |
uuid TEXT PRIMARY KEY, | |
created DATE NOT NULL, | |
content TEXT NOT NULL, | |
CONSTRAINT check_my_table_uuid CHECK (uuid REGEXP '[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}') | |
); | |
DROP TRIGGER IF EXISTS trigger_after_insert_on_my_table; | |
CREATE TRIGGER trigger_after_insert_on_my_table | |
AFTER INSERT ON my_table FOR EACH ROW WHEN NEW.uuid IS NULL | |
BEGIN | |
UPDATE my_table SET uuid = (SELECT next FROM uuid7) WHERE ROWID = NEW.ROWID; | |
END; | |
-- NOTES: | |
-- 1. The trigger generates a UUIDv7 when none is provided in the insert statement. | |
-- 2. The check constraint verifies if the provided UUID is valid on updates and inserts. | |
-- 3. Unfortunately, we can't use a sub-query as DEFAULT value for the PK. That's why we use the trigger. | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Insert some lines using the trigger | |
INSERT INTO my_table VALUES(NULL, DATETIME(), 'Hello, World!'); | |
INSERT INTO my_table VALUES(NULL, DATETIME(), 'Hello, World!'); | |
INSERT INTO my_table VALUES(NULL, DATETIME(), 'Hello, World!'); | |
-- Insert more lines using the view (ignoring the trigger) | |
INSERT INTO my_table VALUES((SELECT next FROM uuid7), DATETIME(), 'Hello, World!'); | |
INSERT INTO my_table VALUES((SELECT next FROM uuid7), DATETIME(), 'Hello, World!'); | |
INSERT INTO my_table VALUES((SELECT next FROM uuid7), DATETIME(), 'Hello, World!'); | |
-- Insert more lines providing UUIDs (also ignoring the trigger) | |
INSERT INTO my_table VALUES('99f30c47-d5be-4803-9f2b-95c232f89877', DATETIME(), 'Hello, World!'); | |
INSERT INTO my_table VALUES('d38ae560-321f-408c-a70b-a5ad8f27d346', DATETIME(), 'Hello, World!'); | |
INSERT INTO my_table VALUES('c78a27ec-b065-4af1-9619-7a676d34275a', DATETIME(), 'Hello, World!'); | |
-- Try to insert lines with invalid UUIDs; they must throw check error | |
INSERT INTO my_table VALUES('', DATETIME(), 'Hello, World!'); | |
INSERT INTO my_table VALUES('asdfasdfasdf', DATETIME(), 'Hello, World!'); | |
INSERT INTO my_table VALUES('0d56252d-51a6-4d1b-8ddc----------', DATETIME(), 'Hello, World!'); | |
SELECT * FROM my_table; | |
-- 01901a7a-3f0b-714e-b696-6d48d23a262e|2024-06-15 05:58:57|Hello, World! | |
-- 01901a7a-3f0b-76fb-82cd-17b01c4e7cfe|2024-06-15 05:58:57|Hello, World! | |
-- 01901a7a-3f0b-7a42-a03b-3055c708f422|2024-06-15 05:58:57|Hello, World! | |
-- 01901a7a-3f0b-7ad1-b2b9-0d4ead036759|2024-06-15 05:58:57|Hello, World! | |
-- 01901a7a-3f0b-7076-ae04-693bd8f276aa|2024-06-15 05:58:57|Hello, World! | |
-- 01901a7a-3f0c-7e05-bae2-4792b2e3192b|2024-06-15 05:58:57|Hello, World! | |
-- 99f30c47-d5be-4803-9f2b-95c232f89877|2024-06-15 05:58:57|Hello, World! | |
-- d38ae560-321f-408c-a70b-a5ad8f27d346|2024-06-15 05:58:57|Hello, World! | |
-- c78a27ec-b065-4af1-9619-7a676d34275a|2024-06-15 05:58:57|Hello, World! | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @fabiolimace, I see now. Thanks for sharing this and explaining your solution!