참조 작업
참조 작업(referential action)은 애플리케이션이 관련 레코드를 삭제하거나 갱신할 때 레코드에 어떤 일이 발생하는지 결정합니다.
버전 2.26.0부터 프리즈마 스키마의 관계 필드에 대한 참조 작업을 정의할 수 있습니다. 이를 통해 프리즈마 수준에서 연속 삭제 및 연속 갱신과 같은 참조 작업을 정의할 수 있습니다.
참조 작업
참조 작업은 update나 delete 질의를 실행할 때 데이터베이스에서 참조된 레코드를 처리하는 방법을 정의하는 정책입니다.
참조 작업을 사용하는 방법
참조 작업은 @relation 속성에 정의되어 있으며, 기반 데이터베이스의 외래 키 제약 조건에 대한 작업에 매핑됩니다. 참조 작업을 별도로 지정하지 않으면 프리즈마는 기본값으로 돌아갑니다.
다음 모델은 명시적으로 정의된 참조 작업을 사용하여 User와 Post 사이의 일대다 관계, Post와 Tag 사이의 다대다 관계를 정의합니다.
prismamodel User {id Int @id @default(autoincrement())posts Post[]}model Post {id Int @id @default(autoincrement())title Stringtags TagOnPosts[]User User? @relation(fields: [userId], references: [id], onDelete: SetNull, onUpdate: Cascade)userId Int?}model TagOnPosts {id Int @id @default(autoincrement())post Post? @relation(fields: [postId], references: [id], onUpdate: Cascade, onDelete: Cascade)tag Tag? @relation(fields: [tagId], references: [id], onUpdate: Cascade, onDelete: Cascade)postId Int?tagId Int?}model Tag {id Int @id @default(autoincrement())name String @uniqueposts TagOnPosts[]}
prismamodel User {id Int @id @default(autoincrement())posts Post[]}model Post {id Int @id @default(autoincrement())title Stringtags TagOnPosts[]User User? @relation(fields: [userId], references: [id], onDelete: SetNull, onUpdate: Cascade)userId Int?}model TagOnPosts {id Int @id @default(autoincrement())post Post? @relation(fields: [postId], references: [id], onUpdate: Cascade, onDelete: Cascade)tag Tag? @relation(fields: [tagId], references: [id], onUpdate: Cascade, onDelete: Cascade)postId Int?tagId Int?}model Tag {id Int @id @default(autoincrement())name String @uniqueposts TagOnPosts[]}
이 모델은 다음 참조 작업을 명시적으로 정의합니다.
Tag를 삭제하면Cascade참조 작업을 사용하여TagOnPosts에서 해당하는 태그 할당도 삭제됩니다.User를 삭제하면SetNull참조 작업으로 인해 필드 값이Null로 바꿔어 작성자가 모든 게시물에서 제거됩니다. 이를 허용하려면Post의User와userId가 선택적 필드여야 합니다.
프리즈마는 다음 참조 작업을 지원합니다.
CascadeRestrictNoActionSetNullSetDefault
참조 작업 기본값
참조 작업을 별도로 지정하지 않으면 프리즈마는 다음 기본값을 사용합니다.
| 절 | 선택적 관계 | 필수 관계 |
|---|---|---|
onDelete | SetNull | Restrict |
onUpdate | Cascade | Cascade |
주의 사항
- 암시적 다대다 관계에서는 참조 작업이 지원되지 않습니다. 참조 작업을 사용하려면 명시적 다대다 관계를 정의하고 조인 테이블에서 참조 작업을 정의해야 합니다.
- 참조 작업과 필수/선택적 관계의 특정 조합은 호환되지 않습니다. 예를 들어 필수 관계에서
SetNull을 사용하면null을 허용하지 않는 제약 조건이 위반되기 때문에 참조된 레코드를 삭제할 때 데이터베이스 오류가 발생합니다. 자세한 내용은 깃허브 이슈를 참고하세요.
참조 작업의 유형
Cascade
onDelete: Cascade- 참조되는 레코드를 삭제하면 참조하는 레코드가 삭제됨onUpdate: Cascade- 종속 레코드의 참조된 스칼라 필드가 갱신되면 관계 스칼라 필드를 갱신함
예시:
prismamodel Post {id Int @id @default(autoincrement())title Stringauthor User @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)authorId Int}model User {id Int @id @default(autoincrement())posts Post[]}
prismamodel Post {id Int @id @default(autoincrement())title Stringauthor User @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)authorId Int}model User {id Int @id @default(autoincrement())posts Post[]}
User 레코드가 삭제되면 해당 게시물도 삭제됩니다. 사용자 id가 갱신되면 해당하는 authorId도 갱신됩니다.
Restrict
onDelete: Restrict- 참조 레코드가 있다면 삭제를 막음onUpdate: Restrict- 참조된 레코드의 식별자가 변경되는 것을 막음
예시:
prismamodel Post {id Int @id @default(autoincrement())title Stringauthor User @relation(fields: [authorId], references: [id], onDelete: Restrict, onUpdate: Restrict)authorId Int}model User {id Int @id @default(autoincrement())posts Post[]}
prismamodel Post {id Int @id @default(autoincrement())title Stringauthor User @relation(fields: [authorId], references: [id], onDelete: Restrict, onUpdate: Restrict)authorId Int}model User {id Int @id @default(autoincrement())posts Post[]}
게시물이 있는 User는 삭제할 수 없습니다. User의 id는 변경할 수 없습니다.
이 Restrict 작업은 마이크로소프트 SQL 서버에서 사용할 수 없으며 스키마 유효성 검사 오류를 발생시킵니다. 대신 동일한 결과를 생성하고 SQL 서버와 호환되는 NoAction를 사용할 수 있습니다.
NoAction
NoAction 작업은 Restrict과 유사하며 둘 사이의 차이점은 사용 중인 데이터베이스에 따라 다릅니다.
- 마이SQL -
NoAction은Restrict와 정확히 동일하게 동작합니다. 자세한 내용은 마이SQL 문서를 참고하세요.
예시:
prismamodel Post {id Int @id @default(autoincrement())title Stringauthor User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction)authorId Int}model User {id Int @id @default(autoincrement())posts Post[]}
prismamodel Post {id Int @id @default(autoincrement())title Stringauthor User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction)authorId Int}model User {id Int @id @default(autoincrement())posts Post[]}
게시물이 있는 User는 삭제할 수 없습니다. User의 id는 변경할 수 없습니다.
SetNull
onDelete: SetNull- 참조하는 개체의 스칼라 필드는NULL로 설정됨onUpdate: SetNull- 참조된 개체의 식별자를 갱신할 때 참조하는 개체의 스칼라 필드는NULL로 설정됨
SetNull은 선택적 관계에서만 작동합니다. 필수 관계에서는 스칼라 필드가 null이 될 수 없으므로 런타임 오류가 발생합니다.
prismamodel Post {id Int @id @default(autoincrement())title Stringauthor User? @relation(fields: [authorId], references: [id], onDelete: SetNull, onUpdate: SetNull)authorId Int?}model User {id Int @id @default(autoincrement())posts Post[]}
prismamodel Post {id Int @id @default(autoincrement())title Stringauthor User? @relation(fields: [authorId], references: [id], onDelete: SetNull, onUpdate: SetNull)authorId Int?}model User {id Int @id @default(autoincrement())posts Post[]}
User를 삭제하면 작성한 모든 게시물의 authorId가 NULL로 설정됩니다.
User의 id를 변경하면 작성한 모든 게시물의 authorId가 NULL로 설정됩니다.
SetDefault
onDelete: SetDefault- 참조하는 객체의 스칼라 필드는 필드 기본값으로 설정됨onUpdate: SetDefault- 참조하는 객체의 스칼라 필드는 필드 기본값으로 설정됨
이를 위해서는 관계형 스칼라 필드의 기본값을 @default로 설정해야 합니다. 스칼라 필드에 기본값이 제공되지 않으면 런타임 오류가 발생합니다.
prismamodel Post {id Int @id @default(autoincrement())title StringauthorUsername String? @default("anonymous")author User? @relation(fields: [authorUsername], references: [username], onDelete: SetDefault, onUpdate: SetDefault)}model User {username String @idposts Post[]}
prismamodel Post {id Int @id @default(autoincrement())title StringauthorUsername String? @default("anonymous")author User? @relation(fields: [authorUsername], references: [username], onDelete: SetDefault, onUpdate: SetDefault)}model User {username String @idposts Post[]}
User를 삭제할 때 기존 게시물의 authorUsername 필드 값이 anonymous로 설정됩니다.
User의 username이 변경되면 기존 게시물의 authorUsername 필드 값이 anonymous로 설정됩니다.