source

복합재 고유 구속조건 후속화

manycodes 2023. 9. 23. 22:51
반응형

복합재 고유 구속조건 후속화

모델 정의:

export default function(sequelize, DataTypes) {
   return sequelize.define('Item', {
       minor: DataTypes.INTEGER,
       major: DataTypes.INTEGER,
   });
}

쌍단조와 장조를 합성 UNIK 제약으로 정의해도 됩니까?

최근 V4에서 Sequelize는 쿼리 인터페이스에 대해 다음과 같은 메서드를 제공합니다.

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' },

조인 테이블인 경우 cellsToMany 연결을 통해 고유한 제약 조건을 만들 수도 있습니다.

Major = sequelize.define('major', {})
Minor = sequelize.define('minor', {})

Major.belongsToMany(Project)
Minor.belongsToMany(User)

출처 : http://docs.sequelizejs.com/en/v3/docs/associations/

저 같은 경우에는 이주를 통해 이를 시행할 수 있는 방법을 찾고 싶었습니다.이 작업은 raw sql 쿼리를 up 기능 끝에 추가하여 수행했습니다.

  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`)'
  );
});

관련 질문:

후속, 외부 키를 복합 기본 키로 사용

Sequelize 모델의 외국키간 고유한 제약조건

다음을 사용하여 이 문제를 해결했습니다.

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

options.indexes[].unique: 색인은 고유하게 작성해야 합니까?유형을 UNIECIAL로 설정하여 트리거할 수도 있습니다.

제이크의 대답에 대한 접근 방식:

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() })

꾸러미의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"
  }
}

Postgre에서 시험한SQL 13.5.

언급URL : https://stackoverflow.com/questions/34664853/sequelize-composite-unique-constraint

반응형