用单次迁移更新数据库



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

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}。它将查找值1,如果找到,它将存储值1,否则将存储值2

{value1, value2}就是这样存储在数据库表中的。所以当我们把它装进长生不老药里时,它看起来像这个["value1", "value2"]

我在这里能做什么?

如果我理解正确,您希望将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

看起来您正试图在关系数据库中创建一个无模式数据库。这会很快变得困难。使用无架构数据库(如couch或mongo(可能会为您提供更好的服务。

然而,如果您使用的是postgres,jsonb或json列类型将更好地服务于这种用例IMO。由于postgres运算符很有趣,因此数据查询起来有点困难,但一旦您了解了它,它就不会太差,并且具有适当索引的性能将与无架构的不相上下。此外,您还可以获得额外的好处,即不必将序列化/反序列化写入数据库层。

最新更新