【问题标题】:Defining interleaved table with different foreign key in Google Cloud Spanner在 Google Cloud Spanner 中定义具有不同外键的交错表
【发布时间】:2020-11-30 18:32:54
【问题描述】:

我正在尝试定义交错表,当父表主表和交错表外键的列名相同时,它可以工作。我已经将我的数据库从 mysql 迁移到 spanner。所有表都以 'id' 作为主键列名。

请考虑以下示例:

CREATE TABLE Singers (
  Id   INT64 NOT NULL,
  FirstName  STRING(1024),
  LastName   STRING(1024),
  SingerInfo BYTES(MAX),
) PRIMARY KEY (Id);

CREATE TABLE Albums (
  SingerId     INT64 NOT NULL,
  Id      INT64 NOT NULL,
  AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, Id),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

这对我不起作用,因为父(歌手)表具有“id”作为主键列,子表具有“SingerId”作为外键。

【问题讨论】:

    标签: database google-cloud-spanner interleave


    【解决方案1】:

    我能够使用 Google Cloud Console 创建表。

    在这里您可以找到等效的 DDL:

    
    CREATE TABLE Singers (
        Id INT64 NOT NULL,
        FirstName STRING(MAX),
        LastName STRING(MAX),
        SingerInfo STRING(MAX),
    ) PRIMARY KEY (Id)
    
    
    CREATE TABLE Albums (
        Id INT64 NOT NULL,
        SingerId INT64 NOT NULL,
        AlbumeTitle STRING(MAX),
    ) PRIMARY KEY (Id, SingerId),
    INTERLEAVE IN PARENT Singers ON DELETE CASCADE
    

    似乎列的顺序很重要。

    父级的主键应该是第一个,因为它是继承的。

    ##EDIT

    它在控制台 UI 上运行

    【讨论】:

    • DB::table('Singers')->insert([ 'Id' => 1234, 'FirstName' => 'Sahilesh', 'LastName' => "Matariya", 'SingerInfo' => 'bla bla' ]); DB::table('Albums')->insert([ 'Id' => 9876, 'SingerId' => 1234, 'AlbumeTitle' => 'sdfsdf' ]);它不允许我添加上面的记录。我得到了以下错误。 “插入失败,因为在父表中找不到键:父表:歌手子表:专辑键:{Int64(9876)}”
    • 这两个表中的 ID 字段必须要求相同的值。它仍然将专辑表中的 ID 字段视为外键。
    • 请参考这些表格,但它是蟑螂db:cockroachlabs.com/docs/stable/…
    • 请检查 Albums 表中的 SingerId 值,它与 Singers 表中的 id 值不同。我想要 SingerId 值 1234 和专辑 id 值 9876。从专辑中选择 Album.Id、Album.AlbumTitle、Singers.FirstName 加入专辑中的歌手。SingerId = Singers.Id;这个查询应该可以工作。
    • 据我了解 Singers id 值和 Album Id 值应该相同,因为 Album 表继承了 Singers Id 。
    【解决方案2】:

    是的,主键规范的顺序很重要。

    更具体地说:

    如果声明一个表为另一个表的子表,则父表的主键列必须是子表主键的前缀。这意味着如果父表的主键由 N 列组成,则其每个子表的主键也必须由相同的 N 列组成,以相同的顺序并从同一列开始。

    参考:https://cloud.google.com/spanner/docs/schema-and-data-model#primary_keys

    【讨论】:

    • 我已经阅读了这个文档并且我遵循了这个模式。 SingerId 已经在专辑表的主键中添加了前缀。你能告诉我我的架构有什么问题吗?
    • 请参考这些表格,但它是蟑螂db:cockroachlabs.com/docs/stable/…
    【解决方案3】:

    只需切换专辑主键的顺序即可解决问题:

    CREATE TABLE Albums (
        SingerId INT64 NOT NULL,
        Id INT64 NOT NULL,
        AlbumeTitle STRING(MAX),
    ) PRIMARY KEY (SingerId, Id),
    INTERLEAVE IN PARENT Singers ON DELETE CASCADE
    

    顺便说一句,如果您只需要通用外键关系,而不需要物理数据交错,您可能需要考虑 Cloud Spanner 中更通用的外键。 你可以参考这里的文档:https://cloud.google.com/spanner/docs/foreign-keys/overview

    要使用通用外键而不是交错,专辑表应如下所示(您将能够保持主键的旧顺序)

    CREATE TABLE Albums (
        Id INT64 NOT NULL,
        SingerId INT64 NOT NULL,
        AlbumeTitle STRING(MAX),
        FOREIGN KEY (SingerId) REFERENCES Singers(SingerId),
    ) PRIMARY KEY (Id, SingerId)
    

    缺点是您不能使用级联删除,因为通用外键尚不支持它。

    【讨论】:

    • 目前我们已经在使用通用外键关系。交错关系对我不起作用。您能否尝试为您的答案的第一个案例播种数据库。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-07
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 2020-06-10
    • 2017-07-05
    • 2018-04-04
    相关资源
    最近更新 更多