You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

咨询:如何用GRDB修改Case_Supplies_Media表的外键引用

修改GRDB中外键引用的正确实现

你的代码存在关键错误:你用UPDATE语句修改列数据,但外键是表结构的约束,并非列存储的值。要修改外键引用,必须调整表结构,而非更新数据。以下是适配GRDB的完整解决方案:

方案1:适配SQLite 3.35.0+(iOS 15+)

SQLite 3.35.0及以上版本支持直接删除外键约束,步骤更简洁:

func updateForeignKey() {
    let currentVersion = ModelData.get_Current_Version()
    
    guard currentVersion == 6 else { return }
    
    do {
        try Database_GRDB.shared.databaseConnection!.write { db in
            // 1. 删除原外键约束(SQLite默认约束名格式:<表名>_<列名>_fkey)
            try db.execute(sql: """
                ALTER TABLE Case_Supplies_Media
                DROP CONSTRAINT Case_Supplies_Media_SupplyID_XRef_fkey;
                """)
            
            // 2. 添加新外键约束,指向Supplies_DVD_List的主键(替换为实际主键列名)
            try db.execute(sql: """
                ALTER TABLE Case_Supplies_Media
                ADD CONSTRAINT fk_CaseSuppliesMedia_SupplyIDXRef_SuppliesDVDList
                FOREIGN KEY(SupplyID_XRef) REFERENCES Supplies_DVD_List(SupplyID);
                """)
            
            // 3. 更新版本号
            try db.execute(sql: """
                UPDATE My_Settings
                SET Version = :version
                WHERE SettingsID = :id;
                """, arguments: ["version": 7, "id": 1])
        }
    } catch {
        print("更新外键约束失败!(AppDelegate) \(error)")
    }
}

方案2:兼容旧版SQLite(iOS 14及以下)

旧版SQLite不支持直接删除约束,需通过重建表实现:

func updateForeignKey() {
    let currentVersion = ModelData.get_Current_Version()
    
    guard currentVersion == 6 else { return }
    
    do {
        try Database_GRDB.shared.databaseConnection!.write { db in
            // 1. 创建新表,复制原表结构并修改外键指向
            try db.execute(sql: """
                CREATE TABLE Case_Supplies_Media_New (
                    -- 复制原表所有列定义(示例包含CaseID,替换为你的实际列)
                    CaseID INTEGER NOT NULL,
                    SupplyID_XRef INTEGER NOT NULL,
                    -- 其他列...
                    PRIMARY KEY(CaseID),
                    FOREIGN KEY(SupplyID_XRef) REFERENCES Supplies_DVD_List(SupplyID)
                );
                """)
            
            // 2. 迁移原表数据到新表
            try db.execute(sql: """
                INSERT INTO Case_Supplies_Media_New
                SELECT * FROM Case_Supplies_Media;
                """)
            
            // 3. 删除原表并重命名新表
            try db.execute(sql: "DROP TABLE Case_Supplies_Media;")
            try db.execute(sql: "ALTER TABLE Case_Supplies_Media_New RENAME TO Case_Supplies_Media;")
            
            // 4. 更新版本号
            try db.execute(sql: """
                UPDATE My_Settings
                SET Version = :version
                WHERE SettingsID = :id;
                """, arguments: ["version": 7, "id": 1])
        }
    } catch {
        print("更新外键约束失败!(AppDelegate) \(error)")
    }
}

关键注意事项

  • 确认原约束名:不确定默认约束名时,可执行PRAGMA foreign_key_list(Case_Supplies_Media);查询外键信息。
  • 匹配主键类型:Supplies_DVD_List的主键列类型必须和SupplyID_XRef完全一致。
  • 事务安全:GRDB的write闭包自动处理事务,任何步骤失败都会回滚所有操作,保证数据一致性。

内容的提问来源于stack exchange,提问作者user11004336

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 05:43:12