Foreign keys
Foreign keys are defined in the constraints object of table definition using the foreignKey function.
Single column
ts
import { integer, foreignKey, primaryKey, table } from "@monolayer/pg/schema";
const users = table({
columns: {
id: integer().generatedAlwaysAsIdentity(),
},
constraints: {
primaryKey: primaryKey(["id"]),
},
});
const documents = table({
columns: {
id: integer().generatedAlwaysAsIdentity(),
userId: integer(),
},
constraints: {
primaryKey: primaryKey(["id"]),
foreignKeys: [
foreignKey(["userId"], users, ["id"]),
],
},
});Multiple of columns
ts
import {
integer,
foreignKey,
primaryKey,
table,
timestampWithTimeZone
} from "@monolayer/pg/schema";
const projects = table({
columns: {
id: integer(),
departmendId: integer(),
},
constraints: {
primaryKey: primaryKey(["id", "departmentId"]),
},
});
const assignments = table({
columns: {
dueDate: timestampWithTimeZone(),
projectId: integer().generatedAlwaysAsIdentity(),
departmentId: integer(),
},
constraints: {
foreignKeys: [
foreignKey(
["projectId", "departmentId"],
projects,
["id", "departmentId"]
),
],
},
});With actions
When you define a foreign key constraint, you can specify actions to taken when the referenced row in the parent table is deleted or updated. There are five actions that you can set when a referenced row is updated or deleted:
| ACTION | Behavior |
|---|---|
| CASCADE | When a referenced row is deleted, row(s) referencing it should be automatically deleted as well |
| SET NULL | Referencing column(s) in the referencing row(s) will be set to NULL when the referenced row is deleted or when the referenced row key is updated |
| SET DEFAULT | Referencing column(s) in the referencing row(s) will be set to their default value when the referenced row is deleted or when the referenced row key is updated |
| RESTRICT | Prevents the deletion of a referenced row up updated of a referenced key |
| NO ACTION | If any referencing rows still exist when the constraint is checked, an error is raised. Similar to RESTRICT. The difference is that NO ACTION allows the check to be deferred until later in the transaction, whereas RESTRICT does not |
INFO
The default action for a foreign key is NO ACTION.
Read more about foreign keys in PostgreSQL - Foreign Keys
Use the modifiers deleteRule and updateRule to specify the foreign key actions:
ts
const documents = table({
columns: {
id: integer().generatedAlwaysAsIdentity(),
userId: integer(),
},
constraints: {
primaryKey: primaryKey(["id"]),
foreignKeys: [
foreignKey(["userId"], users, ["id"])
.deleteRule("set null")
.updateRule("cascade"),
],
},
});Self-referential
ts
import { integer, foreignKey, primaryKey, table } from "@monolayer/pg/schema";
const tree = table({
columns: {
nodeId: integer().generatedAlwaysAsIdentity(),
parentId: integer(),
},
constraints: {
primaryKey: primaryKey(["nodeId"]),
foreignKeys: [
foreignKey(["parentId"], ["nodeId"]),
],
},
});