【问题标题】:updating the database with single migration?使用单一迁移更新数据库?
【发布时间】:2022-02-09 13:39:23
【问题描述】:

我有一个表,其中包含“项目”,该表具有此字段工作区,该工作区采用字符串数组。所以我已将其转换为存储单个字符

 create table("projects") do
  add(:name, :string, null: false)
  add(:title, :string, null: false)
  add(:workspaces, {:array, :string})

  timestamps()
end

我已经编写了这个迁移来存储单个字符串

alter table(:projects) do
      modify(:workspace, :string)

我想运行此迁移,但我也想更新存储在数据库中的所有数据。我需要更新所有工作区数据以存储单个字符串。

假设工作区是否有这个值{value1, value2}。它将查找 value1,如果找到,它将存储 value1,否则将存储 value2

这就是{value1, value2}它在数据库表中的存储方式。所以当我们在 elixir 中加载它时,它看起来像这样 ["value1", "value2"]

我可以在这里做什么?

【问题讨论】:

    标签: elixir ecto


    【解决方案1】:

    如果我理解正确,您想将workspaces 数组列更改为包含数组第一个元素的workspace 字符串列。如果是这种情况,您可以在迁移中执行以下操作:

    # Add the `workspace` column:
    alter table(:projects) do
      add(:workspace, :string)
    end
    
    # Set the value of the new column:
    execute("""
      UPDATE projects SET workspace = CASE
        WHEN 'value1' = ANY(workspaces) THEN 'value1'
        WHEN 'value2' = ANY(workspaces) THEN 'value2'
        ELSE 'default_value'
        END
      """)
    
    # Remove the old column
    alter table(:projects) do
      remove(:workspaces)
    end
    

    【讨论】:

    • 我们可以使用case语句之类的东西吗?
    • 如果未找到 value1,我需要在数组“value1”中查找。然后我应该寻找 value2 然后更新它
    • 我为此编辑了答案。
    • 我们可以回滚这个事务吗?
    • execute 接受第二个参数,即回滚时要执行的查询,如果添加它,您将能够回滚迁移。请记住,这将丢失工作区列表,因为您无法取回信息。您最多只能从workspace 的值创建一个数组。
    【解决方案2】:

    您似乎正在尝试在关系数据库中创建无模式数据库。这很快就会变得困难。使用 couch 或 mongo 等无模式数据库可能会更好地为您服务。

    但是,如果您使用的是 postgres,则 jsonb 或 json 列类型将更好地服务于 IMO 这个用例。数据有点难以查询,因为postgres operators 很有趣,但是一旦你把注意力集中在它上面,它并不算太糟糕,并且具有适当索引的性能将与无模式相提并论。此外,您还可以获得不必将序列化/反序列化写入数据库层的额外好处。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-10
      • 2021-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-17
      • 2018-02-24
      • 1970-01-01
      相关资源
      最近更新 更多