首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >sequelize.sync()是如何工作的,特别是强制选项?

sequelize.sync()是如何工作的,特别是强制选项?
EN

Stack Overflow用户
提问于 2014-01-11 19:20:06
回答 4查看 97.3K关注 0票数 79

sequelize.sync()上的强制选项是做什么的?

代码语言:javascript
运行
复制
sequelize.sync({
    force: true
});

具体来说,我有兴趣知道什么力量:假做什么?它不会将架构与数据库同步吗?

有任何正式的文件用于续写吗?我只能在文档中找到例子。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-01-12 14:07:11

(或多或少)正式文档和API引用可以在https://sequelize.org/docs/v6/core-concepts/model-basics/#model-synchronization上找到。

对于您的问题:force: true在尝试创建表之前添加了一个DROP TABLE IF EXISTS --如果强制,现有的表将被覆盖。

票数 63
EN

Stack Overflow用户

发布于 2016-09-25 16:20:25

操作是问force: false做什么,这也是我想知道的,下面是剩下的。

对我来说,的主要优点是各个字段没有同步(这正是我所希望的,来自Waterline )。这意味着,如果您有force: false ,并且该表存在,则不会执行任何字段添加/修改/删除。

  • 运行beforeSync钩子
  • 如果force: true,则删除表。
  • 表用if not exists创建
  • 如有必要,将添加索引。
  • 运行afterSync钩子

下面是供参考的github回购的当前代码

lib.model.js

代码语言:javascript
运行
复制
Model.prototype.sync = function(options) {
  options = options || {};
  options.hooks = options.hooks === undefined ? true : !!options.hooks;
  options = Utils._.extend({}, this.options, options);

  var self = this
    , attributes = this.tableAttributes;

  return Promise.try(function () {
    if (options.hooks) {
      return self.runHooks('beforeSync', options);
    }
  }).then(function () {
    if (options.force) {
      return self.drop(options);
    }
  }).then(function () {
    return self.QueryInterface.createTable(self.getTableName(options), attributes, options, self);
  }).then(function () {
    return self.QueryInterface.showIndex(self.getTableName(options), options);
  }).then(function (indexes) {
    // Assign an auto-generated name to indexes which are not named by the user
    self.options.indexes = self.QueryInterface.nameIndexes(self.options.indexes, self.tableName);

    indexes = _.filter(self.options.indexes, function (item1) {
      return !_.some(indexes, function (item2) {
        return item1.name === item2.name;
      });
    });

    return Promise.map(indexes, function (index) {
      return self.QueryInterface.addIndex(self.getTableName(options), _.assign({logging: options.logging, benchmark: options.benchmark}, index), self.tableName);
    });
  }).then(function () {
    if (options.hooks) {
      return self.runHooks('afterSync', options);
    }
  }).return(this);
};
票数 52
EN

Stack Overflow用户

发布于 2021-06-03 22:56:10

最小可运行示例

代码语言:javascript
运行
复制
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: 'tmp.sqlite',
});
(async () => {
const IntegerNames = sequelize.define('IntegerNames', {
  value: { type: DataTypes.INTEGER, },
  name: { type: DataTypes.STRING, },
}, {});
//await IntegerNames.sync({force: true})
await IntegerNames.create({value: 2, name: 'two'});
await sequelize.close();
})();

设置:

代码语言:javascript
运行
复制
npm install sequelize@6.5.1 sqlite3@5.0.2.

在stdout上,我们可以看到它执行的查询:

代码语言:javascript
运行
复制
Executing (default): DROP TABLE IF EXISTS `IntegerNames`;
Executing (default): CREATE TABLE IF NOT EXISTS `IntegerNames` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `value` INTEGER, `name` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL);
Executing (default): PRAGMA INDEX_LIST(`IntegerNames`)
Executing (default): INSERT INTO `IntegerNames` (`id`,`value`,`name`,`createdAt`,`updatedAt`) VALUES (NULL,$1,$2,$3,$4);

如果我们使用的是force: false,那么除了一开始没有DROP之外,我们得到了相同的信息:

代码语言:javascript
运行
复制
Executing (default): CREATE TABLE IF NOT EXISTS `IntegerNames` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `value` INTEGER, `name` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL);
Executing (default): PRAGMA INDEX_LIST(`IntegerNames`)
Executing (default): INSERT INTO `IntegerNames` (`id`,`value`,`name`,`createdAt`,`updatedAt`) VALUES (NULL,$1,$2,$3,$4);

如果我们删除同步,则根本不会创建表:

代码语言:javascript
运行
复制
Executing (default): INSERT INTO `IntegerNames` (`id`,`value`,`name`,`createdAt`,`updatedAt`) VALUES (NULL,$1,$2,$3,$4);

经以下测试:

代码语言:javascript
运行
复制
npm install sequelize@6.5.1 sqlite3@5.0.2.

force: false 不同步模式,您需要

使用force: true,数据库将被删除并重新创建,因此它当然与最新的模式相匹配,但您将丢失所有数据。

为了既保留现有数据又更新模式,除了使用alter: true之外,我们还必须使用force: false

下面的工作和标准输出显示了通过创建临时数据库IntegerNames_backup使其工作的复杂查询序列

代码语言:javascript
运行
复制
const assert = require('assert')
const { Sequelize, DataTypes } = require('sequelize');

(async () => {
{
  const sequelize = new Sequelize({
    dialect: 'sqlite',
    storage: 'tmp.sqlite',
  });
  const IntegerNames = sequelize.define('IntegerNames', {
    value: { type: DataTypes.INTEGER, },
    name: { type: DataTypes.STRING, },
  }, {});
  await IntegerNames.sync({force: true})
  await IntegerNames.create({value: 2, name: 'two'});
  await IntegerNames.create({value: 3, name: 'three'});
  await sequelize.close();
}

// Alter by adding column..
{
  const sequelize = new Sequelize({
    dialect: 'sqlite',
    storage: 'tmp.sqlite',
  });
  const IntegerNames = sequelize.define('IntegerNames', {
    value: { type: DataTypes.INTEGER, },
    name: { type: DataTypes.STRING, },
    nameEs: { type: DataTypes.STRING, },
  }, {});
  await IntegerNames.sync({
    alter: true,
    force: false,
  })
  await IntegerNames.create({value: 5, name: 'five' , nameEs: 'cinco'});
  await IntegerNames.create({value: 7, name: 'seven', nameEs: 'siete'});
  const integerNames = await IntegerNames.findAll({
    order: [['value', 'ASC']],
  });
  assert(integerNames[0].value  === 2);
  assert(integerNames[0].name   === 'two');
  assert(integerNames[0].nameEs === null);
  assert(integerNames[1].name   === 'three');
  assert(integerNames[1].nameEs === null);
  assert(integerNames[2].name   === 'five');
  assert(integerNames[2].nameEs === 'cinco');
  assert(integerNames[3].name   === 'seven');
  assert(integerNames[3].nameEs === 'siete');
  await sequelize.close();
}
})();

如果删除alter: true,它就会爆炸,因为新列不存在:

代码语言:javascript
运行
复制
SequelizeDatabaseError: SQLITE_ERROR: table IntegerNames has no column named nameEs

alter的工作方式是创建一个新表,并通过以下方法将所有数据从旧表移动到新表:

代码语言:javascript
运行
复制
Executing (default): CREATE TABLE IF NOT EXISTS `IntegerNames_backup` (`id` INTEGER PRIMARY KEY, `value` INTEGER, `name` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `nameEs` VARCHAR(255));
Executing (default): INSERT INTO `IntegerNames_backup` SELECT `id`, `value`, `name`, `createdAt`, `updatedAt`, `nameEs` FROM `IntegerNames`;
Executing (default): DROP TABLE `IntegerNames`;
Executing (default): CREATE TABLE IF NOT EXISTS `IntegerNames` (`id` INTEGER PRIMARY KEY, `value` INTEGER, `name` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `nameEs` VARCHAR(255));

它不使用ALTER语句,因为SQLite目前不支持它们。这样就打破了后缀不会根据需要自动删除和重新创建的约束:如果外键约束是活动的,则使用后缀迁移更改表的过程,这是相当可悲的。

然而,迁移往往是在实际项目中更新模式的推荐方法:Sequelize:改变生产模式

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21066755

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档