定义模型:
export default function(sequelize, DataTypes) {
return sequelize.define('Item', {
minor: DataTypes.INTEGER,
major: DataTypes.INTEGER,
});
}
我可以将次要和主要对定义为复合 UNIQUE 约束吗?
addConstraint
:
queryInterface.addConstraint('Items', {
fields: ['minor', 'major'],
type: 'unique',
name: 'custom_unique_constraint_name'
});
queryInterface.createTable(
'Item',
{
minor: {
type: Sequelize.INTEGER,
},
major: {
type: Sequelize.INTEGER,
}
},
{
uniqueKeys: {
Items_unique: {
fields: ['minor', 'major']
}
}
}
);
这是简单的答案:
major: { type: DataTypes.INTEGER, unique: 'compositeIndex'},
minor: { type: DataTypes.INTEGER, unique: 'compositeIndex'}
来源:https://sequelize.org/master/manual/model-basics.html#column-options
// Creating two objects with the same value will throw an error. > The unique property can be either a // boolean, or a string. If you provide the same string for > multiple columns, they will form a // composite unique key. uniqueOne: { type: DataTypes.STRING, unique: 'compositeIndex' }, uniqueTwo: { type: DataTypes.INTEGER, unique: 'compositeIndex' },
如果是连接表,您还可以通过belongsToMany关联创建唯一约束:
Major = sequelize.define('major', {})
Minor = sequelize.define('minor', {})
Major.belongsToMany(Project)
Minor.belongsToMany(User)
来源:http://docs.sequelizejs.com/en/v3/docs/associations/
就我而言,我想找到一种方法在迁移中强制执行此操作。我通过在 up 函数末尾附加原始 sql 查询来做到这一点:
up: function(queryInterface, Sequelize) {
return queryInterface.createTable('Item', {
major: {
allowNull: false,
type: Sequelize.INTEGER
},
minor: {
allowNull: false,
type: Sequelize.INTEGER
},
})
.then(function() {
return queryInterface.sequelize.query(
'ALTER TABLE `Item` ADD UNIQUE `unique_index`(`major`, `minor`)'
);
});
相关问题:
addConstraint(...)
解决了这个问题:
await queryInterface.addConstraint('Item', {
fields: ['minor', 'major'],
type: 'unique',
name: 'unique_constraint_name'
});
这是至少从 v6+ 开始的。
你可以使用这样的东西:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.sequelize.transaction(t => {
return queryInterface.createTable('item',
{
minor: {
type: Sequelize.INTEGER,
},
major: {
type: Sequelize.INTEGER,
}
}, { transaction: t }
).then(() => {
return queryInterface.addConstraint(
'item',
['minor', 'major'],
{
type: 'unique',
name: 'Items_unique'
},
{
transaction: t
}
);
});
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('item');
}
}
对于 ES6 迁移
const item = {
up: (queryInterface, Sequelize) => queryInterface.createTable('Items', {
minor: {
type: Sequelize.INTEGER,
allowNull: false,
},
major: {
type: Sequelize.INTEGER,
allowNull: false,
},
}).then(() => queryInterface.addConstraint('Items', ['minor', 'major'], {
type: 'unique',
name: 'composite_key_name'
})),
down: queryInterface => queryInterface.dropTable('Items')
};
export default item;
sequelize.define('', {}, {indexes: [ { unique: true
除了杰克的回答之外,还有另一种方法:
const Item = sequelize.define('Item', {
minor: DataTypes.INTEGER,
major: DataTypes.INTEGER,
}, {
indexes: [
{
fields: ['minor', 'major'],
unique: true,
}
]
}
)
它会根据字段自动创建名称,SQLite 查询:
CREATE TABLE IF NOT EXISTS `Items` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`minor` INTEGER,
`major` INTEGER,
`createdAt` DATETIME NOT NULL,
`updatedAt` DATETIME NOT NULL
);
PRAGMA INDEX_LIST(`Items`)
CREATE UNIQUE INDEX `items_minor_major` ON `Items` (`minor`, `major`)
记录于:https://sequelize.org/master/class/lib/model.js~Model.html#static-method-init
: 索引应该是唯一的吗?也可以通过将类型设置为 UNIQUE 来触发options.indexes[].unique
Jake 的回答方法:
const Item = sequelize.define('Item', {
minor: { type: DataTypes.INTEGER, unique: 'asdf' },
major: { type: DataTypes.INTEGER, unique: 'asdf' },
})
产生一个匿名
UNIQUE
约束(它自动暗示我相信的索引),所以除了名称之外,两者都非常相似:
CREATE TABLE IF NOT EXISTS `Items` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`minor` INTEGER,
`major` INTEGER,
`createdAt` DATETIME NOT NULL,
`updatedAt` DATETIME NOT NULL,
UNIQUE (`minor`, `major`)
);
PRAGMA INDEX_LIST(`Items`)
PRAGMA INDEX_INFO(`sqlite_autoindex_Items_1`)
PostgreSQL 查询是类似的。
完整的可运行示例:
main.js
#!/usr/bin/env node
const assert = require('assert')
const path = require('path')
const { DataTypes, Sequelize } = require('sequelize')
let sequelize
if (process.argv[2] === 'p') {
sequelize = new Sequelize('tmp', undefined, undefined, {
dialect: 'postgres',
host: '/var/run/postgresql',
})
} else {
sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'tmp.sqlite'
})
}
;(async () => {
const Item = sequelize.define('Item', {
minor: DataTypes.INTEGER,
major: DataTypes.INTEGER,
}, {
indexes: [
{
fields: ['minor', 'major'],
unique: true,
}
]
}
)
await Item.sync({ force: true })
await Item.create({ minor: 1, major: 1 })
await Item.create({ minor: 1, major: 2 })
let threw = false
try {
await Item.create({ minor: 1, major: 2 })
} catch (e) {
threw = true
}
assert(threw)
})().finally(() => { return sequelize.close() })
package.json
{
"name": "tmp",
"private": true,
"version": "1.0.0",
"dependencies": {
"pg": "8.5.1",
"pg-hstore": "2.3.3",
"sequelize": "6.14.0",
"sql-formatter": "4.0.2",
"sqlite3": "5.0.2"
}
}
在 PostgreSQL 13.5 上测试。
为了子孙后代,我想提一下这一点。我有一个 Postgres 数据库,正在研究如何添加约束。我们最终使用索引作为约束,在模型上它看起来像这样
sequelize,
tableName: "table_name",
timestamps: false,
paranoid: true,
indexes: [
{
name: "PRIMARY",
unique: true,
using: "BTREE",
fields: [{ name: "field_id" }],
},
{
name: "UniqueConstraint_1",
unique: true,
using: "BTREE",
fields: [
{ name: "user_id" },
{ name: "player_id" },
{ name: "game_id" },
],
},
这将允许您对数据库有一个独特的“约束”。然而,它将显示在索引中而不是约束中。