k-l*_*ine 5 postgresql orm node.js sequelize.js
根据文档, sequelize.sync()没有{force: true}或{alter:true}应该忽略已经存在的表并仅创建/同步新表。但是,至少有两种用例未完全忽略现有表并且会引入错误。
我的设置:
sequelize.sync()用作预迁移步骤来创建架构中不存在的表sequelize.migrate()用于更改任何现有表。注意:Sequelize 模型被视为反映数据库模式的单一事实来源。它们始终会更新以反映数据库中存在的所有索引/字段。
重现步骤
第 1 步:创建具有两个字段和 的User模型。有一个唯一的索引nameemailEmail
const users = sequelizeClient.define('users', {
name: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
},
}, {
indexes: [
{
unique: true,
fields: ['email'],
},
],
});
Run Code Online (Sandbox Code Playgroud)
没有迁移,因此预计将使用sequelize.sync(). 一切都按预期进行。以下是生成的 SQL 脚本。
Executing (default): CREATE TABLE IF NOT EXISTS "users" ("id" SERIAL , "name" VARCHAR(255) NOT NULL, "email" VARCHAR(255) NOT NULL, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'users' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): CREATE UNIQUE INDEX "users_email" ON "users" ("email")
Run Code Online (Sandbox Code Playgroud)
步骤2在Users表中添加新字段phonenumber并添加唯一索引。添加将更改表结构并创建索引的迁移。预计sequelize.sync()会忽略此表,但迁移永远不会执行,因为sequelize.sync()会引发以下错误。
Executing (default): CREATE TABLE IF NOT EXISTS "users" ("id" SERIAL , "name" VARCHAR(255) NOT NULL, "email" VARCHAR(255) NOT NULL, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'users' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): CREATE UNIQUE INDEX "users_phonenumber" ON "users" ("phonenumber")
{"_bitField":18087936,"_fulfillmentHandler0":{"name":"SequelizeDatabaseError","parent":{"name":"error","length":101,"severity":"ERROR","code":"42703","file":"indexcmds.c","line":"1083","routine":"ComputeIndexAttrs","sql":"CREATE UNIQUE INDEX \"users_phonenumber\" ON \"users\" (\"phonenumber\")"},"original":{"name":"error","length":101,"severity":"ERROR","code":"42703","file":"indexcmds.c","line":"1083","routine":"ComputeIndexAttrs","sql":"CREATE UNIQUE INDEX \"users_phonenumber\" ON \"users\" (\"phonenumber\")"},"sql":"CREATE UNIQUE INDEX \"users_phonenumber\" ON \"users\" (\"phonenumber\")"},"_trace":{"_promisesCreated":0,"_length":1},"level":"error","message":"Unhandled Rejection at: Promise "}
Run Code Online (Sandbox Code Playgroud)
这是最终的模型
const users = sequelizeClient.define('users', {
name: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
},
phoneNumber: { // new field
type: DataTypes.STRING,
allowNull: false,
},
}, {
indexes: [
{
unique: true,
fields: ['email'],
},
{ // new index
unique: true,
fields: ['phoneNumber'],
},
],
});
Run Code Online (Sandbox Code Playgroud)
有人可以在这里建议一种解决方法,以便仅在表不存在时才创建索引
另一个用例是当您添加带有注释的新字段时
fieldWithComment: {
type: DataTypes.STRING,
comment: 'my comment goes here',
},
Run Code Online (Sandbox Code Playgroud)
生成的 SQL 显然会抛出错误,因为新列尚不存在。
CREATE TABLE IF NOT EXISTS "users" (
"id" SERIAL,
"name" VARCHAR(255) NOT NULL,
"email" VARCHAR(255) NOT NULL,
"phonenumber" VARCHAR(255) NOT NULL,
"fieldWithComment" VARCHAR(255) , PRIMARY KEY ("id"));
COMMENT ON COLUMN "users"."fieldWithComment" IS 'my comment goes here';
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4949 次 |
| 最近记录: |