Sequelize js,我们如何在迁移中更改列类型
Sequelize js , how do we change column type in migration
我们如何在迁移中更改列类型。在我的迁移 1 中,我有一个添加了该列的迁移。现在我想将列类型从字符串更改为文本,我应该创建一个类似于 changeColumn 的新迁移文件,还是可以创建与迁移 1 相同的新迁移文件,但我只需将类型更改为文本?谢谢。
#迁移 1
await queryInterface.addColumn(SampleModel.tableName, 'name', {
type: Sequelize.STRING,
allowNull: true,
}, {
transaction,
});
迁移 2(创建新的迁移会像这样工作吗?仍然是 addColumn,但我将类型更改为文本)
await queryInterface.addColumn(SampleModel.tableName, 'name', {
type: Sequelize.TEXT,
allowNull: true,
}, {
transaction,
});
您可以在迁移 2 中使用 changeColumn
而不是 addColumn
。
来自the documentation的陈述:
It is possible to change the default value, allowance of null or the data type.
您可以使用 changeColumn
而不是 addColumn
因为 addColumn
会在您的 table 中添加新列。
你可以这样定义你的迁移:
迁移文件
module.exports = {
up: (queryInterface, Sequelize) => {
return Promise.all([
queryInterface.changeColumn('your table name ', 'name', {
type: Sequelize.TEXT,
allowNull: true,
}, {
transaction,
})
])
},
down: (queryInterface, Sequelize) => {
return Promise.all([
queryInterface.changeColumn('your table name ', 'name', {
type: Sequelize.STRING,
allowNull: true,
}, {
transaction,
})
])
}
};
changeColumn
需要注意的错误
我对6.5.1上的那些人真的很困惑,所以我认为在这里留下警告会很好。
错误 1:SQLite 在删除级联时触发
SQLite 没有 ALTER COLUMN
中提到的:
ALTER COLUMN in sqlite
https://sequelize.org/master/class/lib/dialects/sqlite/query-interface.js~SQLiteQueryInterface.html
A wrapper that fixes SQLite's inability to change columns from existing tables. It will create a backup of the table, drop the table afterwards and create a new table with the same name but with a modified version of the respective column.
问题是 sequelize 不需要 ON DELETE CASCADE
执行此操作,因此当它删除原始 table 以重新创建它时,这会触发级联,因此您会丢失数据。
他们需要做的是在迁移之前暂时删除任何级联并在之后恢复它们。我不确定如何解决这个问题,除了将一个迁移与一个删除级联的迁移和另一个恢复级联的迁移包围起来。
值得庆幸的是,在我的用例中它并不重要,因为 SQLite 只是一种快速的本地开发方式,所以如果它每次都对数据库进行核对就很好,因为我可以重新播种它。考虑到 Sequelize 对不同 DBMS 的支持不一致,在本地使用 SQLite 是一个坏习惯。
错误 2:您必须在 PostgreSQL 上通过 type:
,即使您没有更改它
例如,如果您只想更改列的默认值,您可能需要执行以下操作:
await queryInterface.changeColumn('User', 'ip',
{
defaultValue: undefined,
}, { transaction }
);
但是在 PostgreSQL 上这给出了一个错误:
ERROR: Cannot read property 'toString' of undefined
出于某种原因,它没有提供回溯,我喜欢 Node.js 及其生态系统,所以经过一个小时的调试后,我发现 type
是必需的。假设该列的类型为 DataTypes.STRING
,我们将执行:
await queryInterface.changeColumn('User', 'ip',
{
type: Sequelize.DataTypes.STRING,
defaultValue: undefined,
}, { transaction }
);
否则它会尝试在 https://github.com/sequelize/sequelize/blob/v6.5.1/lib/dialects/postgres/query-generator.js#L466 处执行 type.toString()
但 type
未定义。
我们如何在迁移中更改列类型。在我的迁移 1 中,我有一个添加了该列的迁移。现在我想将列类型从字符串更改为文本,我应该创建一个类似于 changeColumn 的新迁移文件,还是可以创建与迁移 1 相同的新迁移文件,但我只需将类型更改为文本?谢谢。
#迁移 1
await queryInterface.addColumn(SampleModel.tableName, 'name', {
type: Sequelize.STRING,
allowNull: true,
}, {
transaction,
});
迁移 2(创建新的迁移会像这样工作吗?仍然是 addColumn,但我将类型更改为文本)
await queryInterface.addColumn(SampleModel.tableName, 'name', {
type: Sequelize.TEXT,
allowNull: true,
}, {
transaction,
});
您可以在迁移 2 中使用 changeColumn
而不是 addColumn
。
来自the documentation的陈述:
It is possible to change the default value, allowance of null or the data type.
您可以使用 changeColumn
而不是 addColumn
因为 addColumn
会在您的 table 中添加新列。
你可以这样定义你的迁移:
迁移文件
module.exports = {
up: (queryInterface, Sequelize) => {
return Promise.all([
queryInterface.changeColumn('your table name ', 'name', {
type: Sequelize.TEXT,
allowNull: true,
}, {
transaction,
})
])
},
down: (queryInterface, Sequelize) => {
return Promise.all([
queryInterface.changeColumn('your table name ', 'name', {
type: Sequelize.STRING,
allowNull: true,
}, {
transaction,
})
])
}
};
changeColumn
需要注意的错误
我对6.5.1上的那些人真的很困惑,所以我认为在这里留下警告会很好。
错误 1:SQLite 在删除级联时触发
SQLite 没有 ALTER COLUMN
中提到的:
ALTER COLUMN in sqlite
https://sequelize.org/master/class/lib/dialects/sqlite/query-interface.js~SQLiteQueryInterface.html
A wrapper that fixes SQLite's inability to change columns from existing tables. It will create a backup of the table, drop the table afterwards and create a new table with the same name but with a modified version of the respective column.
问题是 sequelize 不需要 ON DELETE CASCADE
执行此操作,因此当它删除原始 table 以重新创建它时,这会触发级联,因此您会丢失数据。
他们需要做的是在迁移之前暂时删除任何级联并在之后恢复它们。我不确定如何解决这个问题,除了将一个迁移与一个删除级联的迁移和另一个恢复级联的迁移包围起来。
值得庆幸的是,在我的用例中它并不重要,因为 SQLite 只是一种快速的本地开发方式,所以如果它每次都对数据库进行核对就很好,因为我可以重新播种它。考虑到 Sequelize 对不同 DBMS 的支持不一致,在本地使用 SQLite 是一个坏习惯。
错误 2:您必须在 PostgreSQL 上通过 type:
,即使您没有更改它
例如,如果您只想更改列的默认值,您可能需要执行以下操作:
await queryInterface.changeColumn('User', 'ip',
{
defaultValue: undefined,
}, { transaction }
);
但是在 PostgreSQL 上这给出了一个错误:
ERROR: Cannot read property 'toString' of undefined
出于某种原因,它没有提供回溯,我喜欢 Node.js 及其生态系统,所以经过一个小时的调试后,我发现 type
是必需的。假设该列的类型为 DataTypes.STRING
,我们将执行:
await queryInterface.changeColumn('User', 'ip',
{
type: Sequelize.DataTypes.STRING,
defaultValue: undefined,
}, { transaction }
);
否则它会尝试在 https://github.com/sequelize/sequelize/blob/v6.5.1/lib/dialects/postgres/query-generator.js#L466 处执行 type.toString()
但 type
未定义。