Configuring Table & Column names
We are working on a new Naming Strategy API and seeking feedback. Don't hesitate to take a look at issue #15312.
This chapter is about customizing the name of Database Columns & Tables, not to be confused with JavaScript Attributes & Models.
Table Names
Sequelize will automatically infer table names from your model names, unless a table name is provided manually.
We recommend naming your Models using the singular form of a word, in UpperCamelCase. e.g. User instead of users
By default, Sequelize uses a pluralized version of the model name as the table name.
This pluralization is done under the hood by a library called inflection,
which means irregular plurals (such as person -> people) are computed correctly:
import { Model, Sequelize } from '@sequelize/core';
import { SqliteDialect } from '@sequelize/sqlite3';
class User extends Model {}
const sequelize = new Sequelize({
dialect: SqliteDialect,
models: [User],
});
console.log(User.table.tableName);
// → Users
Snake-case table names
By default, Sequelize does not change the casing of your model name when inferring the table name.
In some databases, it is conventional to have table names in snake_case.
You can make Sequelize generate a snake_cased table name by setting the underscored option.
The underscored option also impacts Column Names. See Snake-case column names.
import { Model, Sequelize } from '@sequelize/core';
import { Table } from '@sequelize/core/decorators-legacy';
import { SqliteDialect } from '@sequelize/sqlite3';
@Table({
underscored: true,
})
class User extends Model {}
const sequelize = new Sequelize({
dialect: SqliteDialect,
models: [User],
});
console.log(User.table.tableName);
// → users (notice the lowercase u)
This behavior can also be defined globally by setting the option in the Sequelize constructor:
import { Model, Sequelize } from '@sequelize/core';
import { SqliteDialect } from '@sequelize/sqlite3';
class User extends Model {}
const sequelize = new Sequelize({
dialect: SqliteDialect,
define: {
underscored: true,
},
models: [User],
});
console.log(User.table.tableName);
// → users
Enforcing the table name to be equal to the model name
You can stop the auto-pluralization performed by Sequelize using the freezeTableName: true option.
Sequelize will use the model name as the table name, without any modifications.
Note that setting freezeTableName also causes Sequelize to ignore the underscored option for table names.
import { SqliteDialect } from '@sequelize/sqlite3';
import { Model, Sequelize } from '@sequelize/core';
import { Table } from '@sequelize/core/decorators-legacy';
@Table({
freezeTableName: true,
})
class User extends Model {}
const sequelize = new Sequelize({
dialect: SqliteDialect,
models: [User],
});
console.log(User.table.tableName);
// → User
This behavior can also be defined globally by setting the option in the Sequelize constructor:
import { Model, Sequelize } from '@sequelize/core';
import { SqliteDialect } from '@sequelize/sqlite3';
class User extends Model {}
const sequelize = new Sequelize({
dialect: SqliteDialect,
define: {
freezeTableName: true,
},
models: [User],
});
console.log(User.table.tableName);
// → User
Manually setting the table name
You can also tell Sequelize the name of the table directly. This will skip any automatic table name generation options and bypass snake_casing and pluralization.
import { Model } from '@sequelize/core';
import { Table } from '@sequelize/core/decorators-legacy';
@Table({ tableName: 'users' })
class User extends Model {}
Column Names
We recommend naming your attributes in lowerCamelCase. e.g. createdAt instead of created_at.
By default, Sequelize will use the name of your attributes as-is as the name of your columns.
Snake-case column names
Just like for table names, the underscored option can be used
to make Sequelize infer snake_cased column names from the attribute names.
This option applies to any attribute that does not explicitly set the columnName option,
including attributes automatically generated by Sequelize such as association foreign-keys and auto-generated timestamps.
In the following example, we have the models User and Task, both using the underscored option.
We also have a One-to-Many relationship between them.
- TypeScript
- JavaScript
import { Model, NonAttribute, InferAttributes, InferCreationAttributes } from '@sequelize/core';
import { Table, Attribute, BelongsTo } from '@sequelize/core/decorators-legacy';
@Table({ underscored: true })
class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
@Attribute(DataTypes.STRING)
declare username: string | null;
}
@Table({ underscored: true })
class Task extends Model {
@Attribute(DataTypes.STRING)
declare title: string | null;
@BelongsTo(() => User)
declare user: NonAttribute<User>;
// added by @BelongsTo
declare UserId: number;
}
import { Model } from '@sequelize/core';
import { Table, Attribute, BelongsTo } from '@sequelize/core/decorators-legacy';
@Table({ underscored: true })
class User extends Model {
@Attribute(DataTypes.STRING)
username;
}
@Table({ underscored: true })
class Task extends Model {
@Attribute(DataTypes.STRING)
title;
@BelongsTo(() => User)
user;
}
Associations automatically add the necessary Foreign Key attributes to your models.
By default, the name of this attribute is equal to the name of the target model + the name of its primary key. In this example,
an attribute called UserId is added on the Task model.
Without the underscored option, Sequelize would automatically define:
- A
createdAtattribute for each model, pointing to a column namedcreatedAtin each table. - An
updatedAtattribute for each model, pointing to a column namedupdatedAtin each table. - A
UserIdattribute in theTaskmodel, pointing to a column namedUserIdin the task table.
With the underscored option enabled, Sequelize will instead define:
- A
createdAtattribute for each model, pointing to a column namedcreated_atin each table. - An
updatedAtattribute for each model, pointing to a column namedupdated_atin each table. - A
UserIdattribute in theTaskmodel, pointing to a column nameduser_idin the task table.
Note that in both cases the fields are still camelCase in the JavaScript side; this option only changes how these fields are mapped to the database itself. The field option of every attribute is set to their snake_case version, but the attribute itself remains camelCase.
With underscored: true, calling sequelize.sync() after the above code will execute the following:
CREATE TABLE IF NOT EXISTS "users" (
"id" SERIAL,
"username" VARCHAR(255),
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL,
"updated_at" TIMESTAMP WITH TIME ZONE NOT NULL,
PRIMARY KEY ("id")
);
CREATE TABLE IF NOT EXISTS "tasks" (
"id" SERIAL,
"title" VARCHAR(255),
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL,
"updated_at" TIMESTAMP WITH TIME ZONE NOT NULL,
"user_id" INTEGER REFERENCES "users" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
PRIMARY KEY ("id")
);
Manually setting the column name
It is also possible to manually set the name of a column by using the @ColumnName decorator.
This name takes precedences and will be used as-is. The underscored option is ignored for this column.
- TypeScript
- JavaScript
import { DataTypes, Model, InferAttributes, InferCreationAttributes } from '@sequelize/core';
import { Attribute, ColumnName } from '@sequelize/core/decorators-legacy';
class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
@Attribute(DataTypes.STRING)
// This attribute will be named "first_name" in SQL, and "firstName" in JavaScript.
@ColumnName('first_name')
declare firstName: number;
}
import { DataTypes, Model } from '@sequelize/core';
import { Attribute, ColumnName } from '@sequelize/core/decorators-legacy';
class User extends Model {
@Attribute(DataTypes.STRING)
// This attribute will be named "first_name" in SQL, and "firstName" in JavaScript.
@ColumnName('first_name')
firstName;
}