【问题标题】:How to insert NULL value to UUID instead of zeros如何将 NULL 值插入 UUID 而不是零
【发布时间】:2022-07-28 22:28:55
【问题描述】:

我在 postgres 中有一个表,其 UUID 字段类型必须是唯一的,但可以为空

有这样的表格和模型

CREATE TABLE IF NOT EXISTS asdf(
    id bigserial primary key,
    name varchar(255) NOT NULL,
    key uuid unique,
    created_at timestamptz,
    updated_at timestamptz
);

go 模型定义为

type Asdf struct {
    ID          uint64    `json:"id" gorm:"type:uuid;column:id"`
    Name        string    `json:"name" gorm:"column:name"`
    Key         uuid.UUID `json:"key" gorm:"column:key"`
    CreatedAt   time.Time `json:"created_at" gorm:"column:created_at"`
    UpdatedAt   time.Time `json:"updated_at" gorm:"column:updated_at"`
}

result := db.Connect().Create(asdf.Asdf{ID:123,Name:"This is the name"})

并将以下 sql 查询打印到终端

INSERT INTO "asdf" ("id","name","key","created_at","updated_at")
VALUES('123','This is the name','00000000-0000-0000-0000-000000000000','2022-04-27 03:41:49.338','2022-04-27 03:41:49.338')

它使用00000000-0000-0000-0000-000000000000作为key值而不是NULL将模型插入数据库

我还注意到字符串类型会发生这种情况,它插入了一个空字符串 '' 而不是 NULL

如何让 gorm 插入 NULL 而不是零/空字符串作为值?

【问题讨论】:

  • 尝试将此字段的类型更改为Key *uuid.UUID。你显然也必须调整你的 go 代码。
  • 我认为 gorm 也支持常规的sql 接口,因此您也可以尝试定义一个实现sql.Scanner 的自定义类型(在sql 上将null 转换为"" -> go转换)和driver.Valuer(来自sql/driver 包,将"" 转换为null on go -> sql 转换)。不过我还没有测试过,所以你必须自己尝试一下。
  • 我已经在类型中添加了星号,它解决了这个问题我也尝试了这个到字符串类型并且也工作了@LeGEC

标签: postgresql go go-gorm


【解决方案1】:

尝试将字段类型更改为指针类型:

type Asdf struct {
    ID          uint64     `json:"id" gorm:"type:uuid;column:id"`
    Name        string     `json:"name" gorm:"column:name"`
    Key         *uuid.UUID `json:"key" gorm:"column:key"`
    CreatedAt   time.Time  `json:"created_at" gorm:"column:created_at"`
    UpdatedAt   time.Time  `json:"updated_at" gorm:"column:updated_at"`
}

你显然也必须调整你的 go 代码(例如:检查 record.Key != nil,访问 *record.Key 而不是 record.Key,等等......)


我认为 gorm 也尊重常规的 sql 接口,所以你也可以尝试定义一个自定义类型来实现:

  • sql.Scanner 在 sql 上将 null 转换为 "" -> 进行转换,
  • driver.Valuer(来自sql/driver 包)将"" 转换为null on go -> sql 转换。

我还没有测试过,所以你必须自己尝试一下。

【讨论】:

  • 实现 ScannerValuer 应该可以工作。
【解决方案2】:

问题中未指定您使用的包。如果你使用satori/go.uuid,你可以使用NullUUID type

type Asdf struct {
    ID          uint64         `json:"id" gorm:"type:uuid;column:id"`
    Name        string         `json:"name" gorm:"column:name"`
    NullableKey uuid.NullUUID `json:"key" gorm:"column:key"`
    CreatedAt   time.Time      `json:"created_at" gorm:"column:created_at"`
    UpdatedAt   time.Time      `json:"updated_at" gorm:"column:updated_at"`
}

设置一个值:

key := uuid.NullUUID{
    Value: id,  // of type uuid.UUID
    Valid: true
}

要保存null,只需保存零值。 ScanValue 方法都已定义。

【讨论】:

    猜你喜欢
    • 2014-12-10
    • 2016-08-30
    • 1970-01-01
    • 2014-04-15
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多