【问题标题】:Using UUIDs in SQLite在 SQLite 中使用 UUID
【发布时间】:2013-06-24 14:18:09
【问题描述】:

是否可以使用UUID 值作为 SQLite 中的主键?我发现有关该主题的信息极为有限,因此我不确定 SQLite 是否支持 UUID 数据类型。我应该将 UUID 存储为字符串吗?

【问题讨论】:

    标签: sqlite uuid


    【解决方案1】:

    SQLite 允许使用任何data type 作为主键。

    UUID 可以存储为字符串(人类可读)或 16 字节 BLOB(如果记录太小以至于差异很重要,这可能会更快)。

    【讨论】:

    • 这两种数据类型在存储 UUID 方面是否比另一种更有效?
    • 对于其他读者……人类可读的 36 个字符的十六进制字符串如下所示:988097c8-3f9c-4ecf-9d1d-64701bb9764c
    • UUID BLOB vs TEXT 文件大小很重要,但是插入和查询的速度差不多,见stackoverflow.com/a/11337522/254109
    【解决方案2】:

    CL 的回答是正确的,但有点绕开了手头的问题。如前所述,任何类型的一列(或多列)都可以用作主键。因此,您可以以格式化的、人类可读的字符串格式存储 UUID,并将其作为您的表的键。而且由于 UUID 只是一个 128 位整数,因此您还可以将整数的字节存储为 BLOB,我想这会稍微快一些。

    但要更直接地回答我认为是手头的问题,不,SQLite 具有任何直接支持 UUID 的功能。当 SQLite 创建表时,它使用列的声明类型来确定它将使用五个底层storage classes(整数、实数、文本、blob 或 null)中的哪一个。创建表后,不使用列的声明类型。因此没有特定于 UUID 的列类型或存储类。似乎也没有任何 functions 可用于转换为格式化的 UUID 字符串。要获取 UUID 的字节,您需要查看编写应用程序的语言提供了哪些方法。例如,Java 的 UUID 类或 Apple 的 NSUUID

    【讨论】:

      【解决方案3】:

      现在有一个 sqlite 扩展,可以根据 https://sqlite.org/src/file/ext/misc/uuid.c 创建有效的 uuid

      【讨论】:

      • 如何添加扩展?
      • 有点繁琐.. 详情请看这里sqlite.org/…
      【解决方案4】:

      不确定是否将其用作默认字段,但如果有人需要在 sqlite 查询中生成唯一值,可以使用以下方法 suggested here

      randomblob(N) 函数返回一个包含伪随机数的 N 字节 blob 字节。如果 N 小于 1,则返回一个 1 字节的随机 blob。 提示:应用程序可以使用这个生成全局唯一标识符 与 hex() 和/或 lower() 一起使用,如下所示:

      hex(randomblob(16)) 
      

      lower(hex(randomblob(16))) 
      

      【讨论】:

      • UUID 不是 randomblob(16),请参阅 stackoverflow.com/a/22725697/254109 如果您不需要确切的 UUID,那么 randomblob 就足够了。
      • 伪随机字节与 UUID 相同。
      【解决方案5】:

      我需要在 sqlite 中实现 UUID,因为它不是本机功能,所以这是我在互联网上遇到的一个技巧。 SQLite 不支持 UUID,所以想法是创建一个函数,使用 randomblob() 函数生成 UUID

      select lower(hex( randomblob(4)) || '-' || hex( randomblob(2))
               || '-' || '4' || substr( hex( randomblob(2)), 2) || '-'
               || substr('AB89', 1 + (abs(random()) % 4) , 1)  ||
               substr(hex(randomblob(2)), 2) || '-' || hex(randomblob(6))) 
      

      这将确保您将有一个 UUID 可以作为varchar 存储在您的表中,所以现在来实现它。 SQLite 不存储函数,因此您可以使用在表中插入新记录后可以调用的触发器

      CREATE TABLE UUID_TABLE(
         id varchar(500),
         name varchar(500) NOT NULL,
         CONSTRAINT name_unique UNIQUE (name),
         CONSTRAINT rid_pkey PRIMARY KEY (id)
      );
      

      和触发器

      CREATE TRIGGER AutoGenerateGUID_RELATION_3
      AFTER INSERT ON UUID_TABLE
      FOR EACH ROW
      WHEN (NEW.relation_id IS NULL)
      BEGIN
         UPDATE UUID_TABLE SET relation_id = (select lower(hex( randomblob(4)) || '-' ||      hex( randomblob(2))
                   || '-' || '4' || substr( hex( randomblob(2)), 2) || '-'
                   || substr('AB89', 1 + (abs(random()) % 4) , 1)  ||
                   substr(hex(randomblob(2)), 2) || '-' || hex(randomblob(6))) ) WHERE rowid = NEW.rowid;
      END;
      

      因此,每当插入新行时,默认情况下 NULL 值将影响到 id,之后触发器会将其修改为存储为 varchar 的新 UUID 值。

      解决方案灵感来自:solution source

      【讨论】:

      • “SQLite 不支持 UUID”到底是什么意思?你是说接受的答案,将近七岁,目前得分为 30,是错误的?
      • 我的意思是 UUID 未定义为 sqlite 中的数据类型,请检查此sqlite.org/datatype3.html 接受的答案表明 UUID 可以作为字符串存储在 sqlite 中。与支持 UUID 作为数据类型的 postgresql 不同,它可以帮助您自动生成 UUID
      • @NicoHaase 接受的答案字面意思是:UUID 可以存储为字符串或 blob。即:sqlite 中没有一流的 UUID 支持。有很多方法可以解释 kaygi22 所说的话,但您可以合理地将其解释为明智。
      • 对于大量的小记录,将 UUID 存储为字符串将占用不成比例的存储量——它可能也不是索引的最佳选择。我希望您可以通过使用类似技术存储 128 位(16 字节)blob 做得更好,但使用按位运算符创建有效的 UUID v4 位 - 然后在客户端层中转换为/从格式化字符串。
      猜你喜欢
      • 2012-12-20
      • 2011-08-16
      • 1970-01-01
      • 2023-01-02
      • 2019-03-21
      • 1970-01-01
      • 2021-05-25
      • 2021-06-11
      • 2010-09-16
      相关资源
      最近更新 更多