メインコンテンツへスキップ

JavaScriptプロジェクトにおけるSQL Serverのイントロスペクション

Prisma ORMでデータベースをイントロスペクトする

このガイドでは、3つのテーブルを持つデモ用SQLスキーマを使用します

CREATE TABLE [dbo].[Post] (
[id] INT NOT NULL IDENTITY(1,1),
[createdAt] DATETIME2 NOT NULL CONSTRAINT [Post_createdAt_df] DEFAULT CURRENT_TIMESTAMP,
[updatedAt] DATETIME2 NOT NULL,
[title] VARCHAR(255) NOT NULL,
[content] NVARCHAR(1000),
[published] BIT NOT NULL CONSTRAINT [Post_published_df] DEFAULT 0,
[authorId] INT NOT NULL,
CONSTRAINT [Post_pkey] PRIMARY KEY ([id])
);

CREATE TABLE [dbo].[Profile] (
[id] INT NOT NULL IDENTITY(1,1),
[bio] NVARCHAR(1000),
[userId] INT NOT NULL,
CONSTRAINT [Profile_pkey] PRIMARY KEY ([id]),
CONSTRAINT [Profile_userId_key] UNIQUE ([userId])
);

CREATE TABLE [dbo].[User] (
[id] INT NOT NULL IDENTITY(1,1),
[email] NVARCHAR(1000) NOT NULL,
[name] NVARCHAR(1000),
CONSTRAINT [User_pkey] PRIMARY KEY ([id]),
CONSTRAINT [User_email_key] UNIQUE ([email])
);

ALTER TABLE [dbo].[Post] ADD CONSTRAINT [Post_authorId_fkey] FOREIGN KEY ([authorId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE;

ALTER TABLE [dbo].[Profile] ADD CONSTRAINT [Profile_userId_fkey] FOREIGN KEY ([userId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE;
テーブルのグラフィカルな概要を展開

ユーザー

列名主キー外部キー必須デフォルト
idINT✔️いいえ✔️自動インクリメント
nameNVARCHAR(1000)いいえいいえいいえ-
emailNVARCHAR(1000)いいえいいえ✔️-

投稿

列名主キー外部キー必須デフォルト
idINT✔️いいえ✔️自動インクリメント
createdAtDATETIME2いいえいいえ✔️now()
updatedAtDATETIME2いいえいいえ✔️
titleVARCHAR(255)いいえいいえ✔️-
contentNVARCHAR(1000)いいえいいえいいえ-
publishedBITいいえいいえ✔️false
authorIdINTいいえ✔️✔️-

プロフィール

列名主キー外部キー必須デフォルト
idINT✔️いいえ✔️自動インクリメント
bioNVARCHAR(1000)いいえいいえいいえ-
userIdINTいいえ✔️✔️-

次のステップとして、データベースをイントロスペクトします。イントロスペクションの結果は、Prismaスキーマ内のデータモデルになります。

データベースをイントロスペクトするには、以下のコマンドを実行します

npx prisma db pull

このコマンドは、.envで定義されているDATABASE_URL環境変数を読み取り、データベースに接続します。接続が確立されると、データベースをイントロスペクトし(つまり、データベーススキーマを読み取ります)、SQLからPrismaデータモデルに変換します。

イントロスペクションが完了すると、Prismaスキーマが更新されます

Introspect your database

データモデルは以下のようになります(モデルのフィールドは読みやすさのために並べ替えられています)。

prisma/schema.prisma
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
createdAt DateTime @default(now()) @db.Timestamp(6)
content String?
published Boolean @default(false)
authorId Int
User User @relation(fields: [authorId], references: [id])
}

model Profile {
id Int @id @default(autoincrement())
bio String?
userId Int @unique
User User @relation(fields: [userId], references: [id])
}

model User {
id Int @id @default(autoincrement())
name String? @db.VarChar(255)
email String @unique @db.VarChar(255)
Post Post[]
Profile Profile?
}

Prismaのデータモデルは、データベーススキーマの宣言的な表現であり、生成されたPrisma Clientライブラリの基盤となります。Prisma Clientインスタンスは、これらのモデルに合わせたクエリを公開します。

現在、データモデルにはいくつか小さな「問題」があります

  • Userリレーションフィールドが大文字になっており、Prismaの命名規則に準拠していません。より「セマンティクス」を表現するためには、このフィールドをauthorと呼んでUserPostの関係をより良く記述できると良いでしょう。
  • User上のPostおよびProfileリレーションフィールド、ならびにProfile上のUserリレーションフィールドはすべて大文字です。Prismaの命名規則に準拠するためには、両方のフィールドをpostprofileuserと小文字にする必要があります。
  • 小文字化しても、User上のpostフィールドはわずかに誤った名前です。それは、実際には投稿のリストを指しているためで、より良い名前は複数形のpostsです。

これらの変更は、生成されるPrisma Client APIにとって重要です。authorpostsprofileuserといった小文字のリレーションフィールドを使用することで、JavaScript/TypeScript開発者にとってより自然で慣用的なものに感じられるでしょう。したがって、Prisma Client APIを構成することができます。

Because リレーションフィールド仮想的である(つまり、データベースに直接現れない)ため、データベースに手を加えることなくPrismaスキーマ内で手動で名前を変更できます。

prisma/schema.prisma
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
createdAt DateTime @default(now()) @db.Timestamp(6)
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
}

model Profile {
id Int @id @default(autoincrement())
bio String?
user User @relation(fields: [userId], references: [id])
userId Int @unique
}

model User {
id Int @id @default(autoincrement())
email String @unique @db.VarChar(255)
name String? @db.VarChar(255)
posts Post[]
profile Profile?
}

この例では、データベーススキーマはPrisma ORMモデルの命名規則に従っていました(イントロスペクションから生成された仮想リレーションフィールドのみがそれに従っておらず、調整が必要でした)。これにより、生成されるPrisma Client APIのエルゴノミクスが最適化されます。

カスタムモデル名とフィールド名の使用

しかし、Prisma Client APIで公開される列名やテーブル名に追加の変更を加えたい場合があります。一般的な例としては、データベーススキーマでよく使用されるsnake_case表記を、JavaScript/TypeScript開発者にとってより自然なPascalCasecamelCase表記に変換することが挙げられます。

snake_case表記に基づいた以下のモデルをイントロスペクションから取得したと仮定します

model my_user {
user_id Int @id @default(autoincrement())
first_name String?
last_name String @unique
}

このモデルのPrisma Client APIを生成した場合、APIにsnake_case表記が採用されます

const user = await prisma.my_user.create({
data: {
first_name: 'Alice',
last_name: 'Smith',
},
})

Prisma Client APIでデータベースのテーブル名や列名を使用しない場合は、@map@@mapを使用して設定できます。

model MyUser {
userId Int @id @default(autoincrement()) @map("user_id")
firstName String? @map("first_name")
lastName String @unique @map("last_name")

@@map("my_user")
}

このアプローチにより、モデルとそのフィールドに好きな名前を付け、@map(フィールド名用)と@@map(モデル名用)を使用して、基になるテーブルと列を指し示すことができます。Prisma Client APIは以下のようになります。

const user = await prisma.myUser.create({
data: {
firstName: 'Alice',
lastName: 'Smith',
},
})

詳細については、「Prisma Client APIの設定」ページを参照してください。

© . All rights reserved.