Golang处理表"TABLE_C"时外键约束"fk_table_c_table_b"冲突的解决方法

Golang处理表"TABLE_C"时外键约束"fk_table_c_table_b"冲突的解决方法 我的代码中有三个表,其中两个是子表,一个是父表。 当我在表C中插入数据时,会抛出以下错误: 在表“TABLE_C”上的插入或更新操作违反了外键约束“fk_table_c_table_b”

type TABLEA  struct {
	TableAId             int    `gorm:"primary_key;NOT NULL AUTO_INCREMENT"`
	UserName            string `gorm:"type:text;"`
	InsertedBy          int    `gorm:"type:int;"`
	InsertedDatatime    time.Time
	LastUpdatedBy       int `gorm:"type:int;"`
	LastUpdatedDatetime time.Time
}

 type TABLEB  struct {
	TableBId              int    `gorm:"primary_key;NOT NULL AUTO_INCREMENT"`
	UserName            string `gorm:"type:text;"`
	InsertedBy          int    `gorm:"type:int;"`
	InsertedDatatime    time.Time
	LastUpdatedBy       int `gorm:"type:int;"`
	LastUpdatedDatetime time.Time
}
type TABLEC struct {
	TableCId              int `gorm:"primaryKey;"`
	TableAId              int    `gorm:"type:int;"`
	TableBId              int `gorm:"type:int;"``
	InsertedBy            int `gorm:"type:int;"`
	InsertedDatetime           time.Time
	LastUpdatedBy         int `gorm:"type:int;"`
	LastUpdatedDatetime   time.Time
	TableA                        TableA       `gorm:"foreignKey:TableAId;references:TableAId;"`
	TableB                        TableB       `gorm:"foreignKey:TableBId ;references:TableBId;"`
}

 data:= TableCDetails{
		TableA:                           tableAModel,
		TableB:                           tableBModel,
		InsertedBy:                       user_id,
		InsertedDatetime:                    time.Now(),
		LastUpdatedDatetime:                 time.Now(),
	}

if err := DB.Create(data).Error; err != nil {
		return err
	}

更多关于Golang处理表"TABLE_C"时外键约束"fk_table_c_table_b"冲突的解决方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

你好,@sumit-kapoor,欢迎来到论坛。

尝试移除 TableB 结构体标签中的空格:

foreignKey:TableBId ;
// 这个 -------^

我不太了解 GORM 的具体细节,但一般来说,结构体标签中的空格可能是重要的。因此,GORM 可能会将该空格视为值的一部分。

更多关于Golang处理表"TABLE_C"时外键约束"fk_table_c_table_b"冲突的解决方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


外键约束冲突通常是由于插入的TableBId在父表TABLEB中不存在。以下是具体解决方法:

1. 确保关联数据已存在 在插入TABLEC之前,先确认关联的TABLEB记录已存在:

// 检查TableB记录是否存在
var tableBRecord TABLEB
if err := DB.First(&tableBRecord, tableBModel.TableBId).Error; err != nil {
    // 如果不存在,先创建TableB记录
    if errors.Is(err, gorm.ErrRecordNotFound) {
        if err := DB.Create(&tableBModel).Error; err != nil {
            return fmt.Errorf("创建TableB失败: %v", err)
        }
    } else {
        return fmt.Errorf("查询TableB失败: %v", err)
    }
}

// 同样检查TableA记录
var tableARecord TABLEA
if err := DB.First(&tableARecord, tableAModel.TableAId).Error; err != nil {
    if errors.Is(err, gorm.ErrRecordNotFound) {
        if err := DB.Create(&tableAModel).Error; err != nil {
            return fmt.Errorf("创建TableA失败: %v", err)
        }
    } else {
        return fmt.Errorf("查询TableA失败: %v", err)
    }
}

// 现在插入TABLEC
data := TABLEC{
    TableAId:            tableAModel.TableAId,
    TableBId:            tableBModel.TableBId,
    InsertedBy:          user_id,
    InsertedDatetime:    time.Now(),
    LastUpdatedDatetime: time.Now(),
}

if err := DB.Create(&data).Error; err != nil {
    return fmt.Errorf("创建TableC失败: %v", err)
}

2. 使用事务确保数据一致性

err := DB.Transaction(func(tx *gorm.DB) error {
    // 创建TableA
    if err := tx.Create(&tableAModel).Error; err != nil {
        return err
    }
    
    // 创建TableB
    if err := tx.Create(&tableBModel).Error; err != nil {
        return err
    }
    
    // 创建TableC
    data := TABLEC{
        TableAId:            tableAModel.TableAId,
        TableBId:            tableBModel.TableBId,
        InsertedBy:          user_id,
        InsertedDatetime:    time.Now(),
        LastUpdatedDatetime: time.Now(),
    }
    
    if err := tx.Create(&data).Error; err != nil {
        return err
    }
    
    return nil
})

if err != nil {
    return fmt.Errorf("事务执行失败: %v", err)
}

3. 使用关联创建(如果使用GORM的关联功能)

// 确保TableA和TableB已设置主键ID
tableAModel.TableAId = 0 // 如果ID为0,GORM会自动生成
tableBModel.TableBId = 0

data := TABLEC{
    TableA:              tableAModel,
    TableB:              tableBModel,
    InsertedBy:          user_id,
    InsertedDatetime:    time.Now(),
    LastUpdatedDatetime: time.Now(),
}

// 使用Select明确指定要创建的字段
if err := DB.Select("TableA", "TableB", "InsertedBy", "InsertedDatetime", "LastUpdatedDatetime").Create(&data).Error; err != nil {
    return fmt.Errorf("创建TableC失败: %v", err)
}

4. 检查外键约束定义 确保数据库中的外键约束与GORM标签匹配:

type TABLEC struct {
    TableCId            int `gorm:"primaryKey;autoIncrement"`
    TableAId            int `gorm:"type:int;not null"`
    TableBId            int `gorm:"type:int;not null"`
    InsertedBy          int `gorm:"type:int"`
    InsertedDatetime    time.Time
    LastUpdatedBy       int `gorm:"type:int"`
    LastUpdatedDatetime time.Time
    TableA              TableA `gorm:"foreignKey:TableAId;references:TableAId;constraint:OnUpdate:CASCADE,OnDelete:RESTRICT"`
    TableB              TableB `gorm:"foreignKey:TableBId;references:TableBId;constraint:OnUpdate:CASCADE,OnDelete:RESTRICT"`
}

关键点:

  1. 插入TABLEC前确保TableAIdTableBId对应的记录已存在
  2. 使用事务保证所有相关表的插入操作原子性
  3. 检查GORM标签中的外键配置是否正确
  4. 验证数据库中外键约束的实际定义是否与代码一致
回到顶部