無料のAzure SQL DatabaseにPrismaを使ってモデルファーストでテーブルを作成したメモ

## 概要
前回、[SQLServer無料版](https://qiita.com/hibohiboo/items/4e8c6f8e841df1909b20)を試した。
今回は、Prismaを使って[モデルファースト](https://www.prisma.io/docs/orm/prisma-migrate/understanding-prisma-migrate/mental-model)で開発したい。

[Prisma を使った効率的なバックエンド開発ワークフロー](https://zenn.dev/optimisuke/articles/387b30c547ac54)に従おうとしたが、`prisma migrate dev --create-only --name newMigration`でmigrationsを作ることに失敗した。Prismaには、シャドウデータベースという、もう一つのデータベースが必要なようだ。

[シャドウ データベースの作成](https://learn.microsoft.com/ja-jp/shows/beginners-series-to-learn-a-full-stack-application-with-azure-sql-prisma/creating-shadow-database-26-of-37-learn-a-full-stack-application-with-azure-sql-prisma-for-beginners)の動画もあったが、無料枠のDBは一つなので断念。ローカルのDBをシャドウデータベースとして試してみる。


## ローカル開発環境の構築
[Azure SQL Database のローカル発環境用のプロジェクトを作成する](https://learn.microsoft.com/ja-jp/azure/azure-sql/database/local-dev-experience-create-database-project?view=azuresql)に沿って構築しようとしたが、途中で面倒になった。

<details><summary>面倒になるまで</summary><div>

[Azure SQL Database のローカル開発環境を設定する](https://learn.microsoft.com/ja-jp/azure/azure-sql/database/local-dev-experience-create-database-project?view=azuresql)の手順通り、[mssql](https://marketplace.visualstudio.com/items?itemName=ms-mssql.mssql)をVSCodeに導入。[Docker Desktop](https://community.chocolatey.org/packages/docker-desktop)は既に導入済だった。

[Azure SQL Database のローカル発環境用のプロジェクトを作成する](https://learn.microsoft.com/ja-jp/azure/azure-sql/database/local-dev-experience-create-database-project?view=azuresql)の手順にそって進めていく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/c3775c75-ebfd-5c1c-1364-0c88332be39e.png)

今回は、「Azure SQL Database」を選択し、プロジェクト名は「YakumiDB」とした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/185ee8c9-8b87-d23b-d2ac-227ec40e2ba3.png)

[プロジェクトをビルドして公開する](https://learn.microsoft.com/ja-jp/azure-data-studio/extensions/sql-database-project-extension-build)の手順を行う。

.NET 6 が必要だよって言われて面倒になってきた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/58084051-cc6f-246e-1411-0e6fe40f5de6.png)

</div>
</details>

[Azure 向け開発のためのローカルリソース準備](https://zenn.dev/tan_y/articles/f213f70f2816bd) より、Dockerを使った構築に切り替える。

[環境変数](https://learn.microsoft.com/ja-jp/sql/linux/sql-server-linux-configure-environment-variables?view=sql-server-ver16#use-with-initial-setup)

```docker-compose.yml
services:
  mssql:
    image: mcr.microsoft.com/mssql/server:2022-latest
    user: root
    container_name: mssql
    ports:
      - 127.0.0.1:1433:1433
    environment:
      - ACCEPT_EULA=Y
      - MSSQL_SA_PASSWORD=<YourStrong@Passw0rd>
      - MSSQL_PID=Developer
      - MSSQL_COLLATION=Japanese_CI_AS
```

```bin/up.sh
#!/bin/bash

bin_dir=$(cd $(dirname $0) && pwd)
docker_dir=$(cd $bin_dir/.. && pwd)
composeFile=${1:-"docker-compose.yml"}
cd $docker_dir && docker-compose -f $composeFile up
```

```bin/bash.sh
#!/bin/bash

bin_dir=$(cd $(dirname $0) && pwd)
docker_dir=$(cd $bin_dir/.. && pwd)
container_name=${1:-mssql}
docker ps | grep $container_name
if [ $? -eq 0 ]; then
  cd $docker_dir && docker-compose exec $container_name bash
else
  cd $docker_dir && docker-compose run --service-ports $container_name bash
fi
```

`./bin/up.sh`でDockerを立ち上げる。
`./bin/bash.sh`でコンテナ内に入り、[SQL Server on Docker](https://www.prisma.io/docs/orm/overview/databases/sql-server/sql-server-docker)に従って`quickstart`データベースを作成する。

sqlcmdの立ち上げ
```
/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P MyPassword123
```

クエリの実行

```
CREATE DATABASE quickstart
GO
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/3faa2648-208d-aded-3777-f992be6bc772.png)

データベースに接続できることを確認する。

```
Username: SA
Password: <YourStrong@Passw0rd>
Database: quickstart
Port: 1433
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/b217d295-9ecc-f04f-46fa-21cb923f98e3.png)

## マイグレーションファイルの作成

```schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlserver"
  url      = env("DATABASE_URL")
  shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}

model Test {
  id      String   @id
  data    String
  created DateTime @default(now()) @db.DateTime
  updated DateTime @default(now()) @updatedAt @db.DateTime
}
```

```.env
DATABASE_URL=sqlserver://hoge.database.windows.net:1433;database=fuga;user=piyo;password=piyopiyo;encrypt=true
SHADOW_DATABASE_URL=sqlserver://localhost:1433;database=quickstart;username=SA;password=<YourStrong@Passw0rd>;trustServerCertificate=true;
```

`prisma migrate dev --create-only --name newMigration`を実行したところ、`All data will be lost`とのこと。Docker内で作ったばかりのデータベースなので、失うものはなにもない。`y`を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/baca5dcf-cf1c-9cbc-69b2-91ad7a8a92d3.png)

ぶじ、`migrations`フォルダ内にマイグレーション用SQLが作成された。

```sql:migrations/yyyyMMddHHmmss_new_migration/migration.sql
BEGIN TRY

BEGIN TRAN;

-- CreateTable
CREATE TABLE [dbo].[Test] (
    [id] NVARCHAR(1000) NOT NULL,
    [data] NVARCHAR(1000) NOT NULL,
    [created] DATETIME NOT NULL CONSTRAINT [Test_created_df] DEFAULT CURRENT_TIMESTAMP,
    [updated] DATETIME NOT NULL CONSTRAINT [Test_updated_df] DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT [Test_pkey] PRIMARY KEY CLUSTERED ([id])
);

COMMIT TRAN;

END TRY
BEGIN CATCH

IF @@TRANCOUNT > 0
BEGIN
    ROLLBACK TRAN;
END;
THROW

END CATCH

```

## Azure SQL Databaseに反映
`prisma migrate deploy`を実行。
```sql
select * from Test;
```

テーブルが作成されたことを確認した。



```
select * from dbo._prisma_migrations;
```

マイグレーションの履歴も残っていることを確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/aebe853a-ea2e-41e3-5844-d029f14abfc3.png)


## 参考
[Azure 向け開発のためのローカルリソース準備](https://zenn.dev/tan_y/articles/f213f70f2816bd)
[Azure SQL Database のローカル開発エクスペリエンスとは](https://learn.microsoft.com/ja-jp/azure/azure-sql/database/local-dev-experience-overview?view=azuresql)
[Azure Data Studioのプレビュー機能を駆使してローカルのSQLサーバを構築してみた](https://zenn.dev/tomodo_ysys/articles/sql-server-local-setup-az-data-studio)
[SQL Server](https://www.prisma.io/docs/orm/overview/databases/sql-server)
[Prisma を使った効率的なバックエンド開発ワークフロー](https://zenn.dev/optimisuke/articles/387b30c547ac54)
[PrismaでSQLの作成や管理、反映の手間を削減する](https://qiita.com/teradatk/items/8efcaf9e8ba0ee8bc6da)