将 PositiveIntegerField 迁移到 FloatField

Migrate a PositiveIntegerField to a FloatField

我有一个现有的填充数据库,想将 PositiveIntegerField 转换为 FloatField。我正在考虑简单地进行迁移:

    migrations.AlterField(
        model_name='mymodel',
        name='field_to_convert',
        field=models.FloatField(
            blank=True,
            help_text='my helpful text',
            null=True),
    ),

当前字段定义为:

field_to_convert = models.PositiveIntegerField(
    null=True,
    blank=True,
    help_text='my helpful text')

这是否需要完全重写数据库列?对于更大的数据库,这种转换的扩展性如何?如果绝大多数值是 null,它会如何扩展?这种转换在什么情况下会失败?如果有所不同,这是由 Postgres 数据库支持的。

您可以使用 sqlmigrate 检查为您的迁移生成的 sql。

$ python manage.py sqlmigrate app_label migration_name

请记住,它的输出取决于 Django 版本和您在设置中的数据库。对于我手头的设置(Django 1.11,Postgres 9.3),我得到了:

BEGIN;
--
-- Alter field field_to_convert on mymodel
--
ALTER TABLE "myapp_mymodel" DROP CONSTRAINT "myapp_mymodel_field_to_convert_check";
ALTER TABLE "myapp_mymodel" ALTER COLUMN "field_to_convert" TYPE double precision USING "field_to_convert"::double precision;
COMMIT;

我觉得它在性能和可靠性方面都不错。我会说继续使用 AlterField。

如果您想更加安全,可以随时执行:重命名字段 -> 创建字段 -> 运行 python -> 删除字段。这将使您更好地控制迁移过程。查看 了解详情。

这是否需要完全重写数据库列?

不,不会。我用 PostgreSQL、MySQL 和 SQL 做了一个实验,从整数到浮点数的转换在每种情况下都很顺利,我还将一些值设置为 null 以匹配您的情况。

如果您有一个值 3,它将变为 3.0

如果绝大多数值为空,它会如何扩展?

好吧,由于您在字段配置中保留了 null=True,因此所有空值都将保持为空,这没有问题。如果删除 null=True,您可能需要指定一个 default 值。

这种转换在什么情况下会失败?

取一个 int 列并将其转换为 float(real)应该不会失败,如果你发现一个奇怪的、奇怪的和非常特殊的情况,那将是一个非常大的发现。

如果您对迁移结果有疑问...

...你可以先看看 SQL 和 sqlmigrate 的迁移,当然,你可以备份你的数据库。