SQL Database Projects extension for Visual Studio Codeでテーブル名やスキーマを変更するときは、SQLファイルを直接書き換えるのではなく、VS CodeのRename SymbolまたはRefactor > Move to Schemaを使うことが重要です。
これらの操作を使うと、変更内容が.refactorlogに記録されます。デプロイ時には、旧テーブルの削除と新規作成ではなく、sp_renameやALTER SCHEMA ... TRANSFERが生成されるため、既存データのコピーや再投入を避けられます。(Microsoft Developer Blogs)
ただし、データが保持されることと、アプリケーションを無停止で更新できることは別問題です。プロジェクト外のSQL、アプリケーション、ETL、レポートなどの参照は自動更新されないため、生成されたデプロイ計画と外部依存関係を必ず確認する必要があります。
VS CodeのSQL Projectsで再作成を避ける方法
テーブル名やスキーマを変更する際の正しい操作は、次のとおりです。
| 変更内容 | VS Codeで使う操作 | デプロイ時の主な処理 | データコピー |
|---|---|---|---|
| テーブル名の変更 | Rename Symbol | sp_rename | 原則不要 |
| 列名の変更 | Rename Symbol | sp_rename | 原則不要 |
| テーブルのスキーマ移動 | Refactor > Move to Schema | ALTER SCHEMA ... TRANSFER | 原則不要 |
| SQL定義を直接書き換える | 手動編集 | 旧オブジェクト削除+新規作成と判断される可能性 | 発生する可能性あり |
SQL Database Projectsは、プロジェクトに記述された「完成後のデータベース定義」と対象データベースを比較し、必要な変更を動的に計画する宣言型の仕組みです。
そのため、次のようにオブジェクト名だけを書き換えても、ツール側は名前変更だと判断できません。
-- 変更前
CREATE TABLE [SalesLT].[SalesOrderDetail]
(
[SalesOrderID] INT NOT NULL
);
-- 変更後
CREATE TABLE [SalesLT].[SalesOrderLine]
(
[SalesOrderID] INT NOT NULL
);
変更意図が記録されていなければ、デプロイ側からは「SalesOrderDetailがなくなり、SalesOrderLineが追加された」ように見えます。その結果、旧テーブルの削除と新規テーブルの作成として処理される可能性があります。
.refactorlogは、この差分が削除と追加ではなく、同じオブジェクトの名前変更やスキーマ移動であることを伝える役割を持ちます。(Microsoft Learn)
refactorlogが名前変更の意図をデプロイへ伝える
.refactorlogは、データベースオブジェクトに対して実施したリファクタリング操作を記録するXMLファイルです。
処理の流れは次のようになります。
- VS Codeでテーブル名変更やスキーマ移動を実行する
- SQLファイル内の定義と参照が更新される
- 操作内容が
.refactorlogへ追加される - ビルド時にrefactorlogが
.dacpac内のrefactor.xmlへ格納される - デプロイ時に対象データベースの適用状況が確認される
- 未適用の場合だけ
sp_renameやALTER SCHEMA ... TRANSFERが実行される - 操作キーが
dbo.__RefactorLogへ記録される
この仕組みにより、開発環境、検証環境、本番環境など、適用状況が異なる複数のデータベースへ同じ.dacpacを展開できます。各データベースでは、操作ごとに一意なキーを使って適用済みかどうかが判断されます。(Microsoft Learn)
refactorlogはソース管理に必ず含める
VS Codeでリファクタリングを実行すると、一般的には次のようなファイルが作成または更新されます。
MyDatabase.refactorlog
このファイルは、通常のSQLファイルや.sqlprojと一緒にGitへコミットしてください。
refactorlogを削除すると、まだ変更が適用されていない環境へデプロイするときに、過去の名前変更を判定できなくなります。その結果、旧オブジェクトの削除と新規作成として処理され、データ損失につながる可能性があります。(Microsoft Learn)
手動でrefactorlogを追加する場合は、.sqlprojにも対象ファイルを登録します。
<ItemGroup>
<RefactorLog Include="MyDatabase.refactorlog" />
</ItemGroup>
ただし、操作キーにはリファクタリングごとに新しいGUIDが必要です。オブジェクト種別、旧名、操作順序などを誤ると、ビルドやパッケージ化に失敗する可能性があります。通常はXMLを手で作成せず、VS Codeのリファクタリング機能に生成させる方が安全です。(Microsoft Learn)
リファクタリング前に確認すること
本番データベースで作業する前に、次の準備を行います。
- SQLプロジェクトが現在のデータベース構成を正しく表しているか確認する
- Schema Compareで意図しない差分がないか確認する
- リファクタリング専用のブランチを作成する
- 本番相当のデータを持つ検証環境を用意する
- アプリケーションとデータベースの更新順序を決める
- 外部システム、バッチ、レポートからの参照を洗い出す
プロジェクトと対象データベースの間に大きなドリフトがある状態で名前変更を始めると、リファクタリングとは無関係な変更まで同じデプロイ計画へ含まれます。
最初にSchema Compareを実行し、現在の差分を整理してから作業するのが安全です。VS CodeのSchema Compareでは、名前変更やスキーマ移動として認識されたオブジェクトも比較結果上で確認できます。(Microsoft Learn)
Rename Symbolでテーブル名を変更する手順
ここでは、次のテーブル名を変更する例で説明します。
変更前:SalesLT.SalesOrderDetail
変更後:SalesLT.SalesOrderLine
テーブル名変更の操作
- VS CodeでSQL Database Projectsのビューを開く
- 対象テーブルのSQLファイルを開く
CREATE TABLE内のテーブル名を右クリックするRename Symbolを選択する- 新しい名前として
SalesOrderLineを入力する - すぐに適用せず、可能であれば変更プレビューを開く
- 更新対象となるビュー、ストアドプロシージャ、関数などを確認する
- 問題がなければ変更を適用する
.refactorlogが更新されていることを確認する- SQLプロジェクトをビルドする
Rename Symbolはテーブル定義だけでなく、SQLプロジェクト内で解決できる参照もまとめて更新します。テーブル本体ではなく、そのテーブルを参照しているビューの定義上からリファクタリングを開始することもできます。(Microsoft Developer Blogs)
デプロイスクリプトには、次のような処理が生成されます。
EXECUTE sys.sp_rename
@objname = N'[SalesLT].[SalesOrderDetail]',
@newname = N'SalesOrderLine',
@objtype = N'OBJECT';
@newnameにはスキーマ名を含めず、新しいオブジェクト名だけを指定します。テーブル名の変更では既存テーブルをその場で改名するため、通常は全レコードを別テーブルへコピーする処理は発生しません。(Microsoft Learn)
SQLファイル名だけを変えてもリファクタリングにはならない
たとえば、次のファイル名を変更しただけでは、データベース上のテーブル名変更として記録されません。
SalesOrderDetail.sql
↓
SalesOrderLine.sql
SQLプロジェクトでは、ファイル名ではなく、ファイル内のデータベース定義が比較対象になります。
先にRename Symbolでオブジェクト名を変更し、その後、必要に応じてファイル名やフォルダーを整理してください。
列名も同じ方法で変更できる
列名についても、対象列を右クリックしてRename Symbolを実行します。
生成される処理は、次のようなsp_renameです。
EXECUTE sys.sp_rename
@objname = N'[SalesLT].[SalesOrderLine].[OrderQty]',
@newname = N'Quantity',
@objtype = N'COLUMN';
ただし、列名変更には注意点があります。SELECT *を使っている非スキーマバインドのビューや関数は、定義内に旧列名が直接書かれていないため、参照更新だけではメタデータが更新されない場合があります。
Microsoftは、このような場合にsp_refreshviewやsp_refreshsqlmoduleによるメタデータ更新を案内しています。生成されたデプロイスクリプトに必要な更新処理が含まれているか確認してください。(Microsoft Learn)
Refactorでテーブルを別スキーマへ移動する手順
ここでは、次のようにテーブルを移動する例で説明します。
変更前:SalesLT.ProductDescription
変更後:ProductCatalog.ProductDescription
新しいスキーマをプロジェクトへ追加する
移動先のスキーマが存在しない場合は、最初にプロジェクトへ追加します。
- Database Projectsビューでプロジェクトを右クリックする
Add item...を選択する- テンプレートから
Schemaを選択する - スキーマ名として
ProductCatalogを入力する
作成される定義は、次のようになります。
CREATE SCHEMA [ProductCatalog];
Move to Schemaを実行する
- 移動対象テーブルのSQLファイルを開く
CREATE TABLE内のテーブル名を右クリックするRefactorを選択するMove to Schemaを選択する- 移動先として
ProductCatalogを選択する - Refactor Previewで変更内容を確認する
- テーブル定義と参照先の更新を確認する
.refactorlogの変更を確認する- 問題がなければ適用する
VS Codeでは、SQLプロジェクト内に定義されているユーザースキーマが選択肢として表示されます。変更プレビューには、テーブル定義、関連オブジェクトの参照、refactorlogへの追加内容が表示されます。(Microsoft Developer Blogs)
デプロイ時には、次のような処理が生成されます。
CREATE SCHEMA [ProductCatalog];
GO
ALTER SCHEMA [ProductCatalog]
TRANSFER [SalesLT].[ProductDescription];
GO
ALTER SCHEMA ... TRANSFERは、既存テーブルを別のスキーマへ移動する処理です。新しいテーブルを作ってデータをコピーする方式ではありません。(Microsoft Developer Blogs)
スキーマ移動では権限を必ず確認する
ALTER SCHEMA ... TRANSFERでオブジェクトを移動すると、そのオブジェクトに直接付与されていた権限は削除されます。
たとえば、次のようなテーブル単位の権限です。
GRANT SELECT
ON OBJECT::[SalesLT].[ProductDescription]
TO [ReportingRole];
必要な権限はSQLプロジェクト側にも定義し、生成されたデプロイスクリプトに新しいオブジェクト名への再付与が含まれているか確認してください。
作業前の権限は、次のようなクエリで確認できます。
SELECT
USER_NAME(grantee_principal_id) AS grantee_name,
permission_name,
state_desc
FROM sys.database_permissions
WHERE major_id = OBJECT_ID(N'[SalesLT].[ProductDescription]');
データベース上だけで手作業により付与された権限は、SQLプロジェクトが把握していない可能性があります。スキーマ移動前に、対象オブジェクトのGRANT、DENY、REVOKEを必ず確認してください。(Microsoft Learn)
また、ALTER SCHEMAはスキーマレベルのロックを使用します。データコピーが発生しなくても、実行中にほかの処理が待機する可能性があるため、アクセスの多い本番環境ではロック待ちを含めて事前検証が必要です。(Microsoft Learn)
自動更新される参照と手動確認が必要な参照
VS Codeのリファクタリング機能が更新できるのは、基本的にSQLプロジェクト内で認識できる参照です。
| 参照元 | 自動更新の期待 | 確認方法 |
|---|---|---|
| プロジェクト内のビュー | 高い | Refactor Previewとビルド |
| プロジェクト内のストアドプロシージャ | 高い | Refactor Previewと全文検索 |
| プロジェクト内の関数・トリガー | 高い | Refactor Previewとビルド |
| SQL文字列として組み立てる動的SQL | 低い | 旧名称の全文検索 |
| アプリケーション内のSQL | 対象外 | ソースコード検索 |
| ORMのテーブルマッピング | 対象外 | エンティティ設定やマイグレーション確認 |
| SQL Server Agentジョブ | 対象外の場合あり | ジョブステップ確認 |
| ETL・データ連携 | 対象外 | ADF、SSIS、スクリプトなどを確認 |
| Power BIや帳票 | 対象外 | データセットとクエリ確認 |
| 別データベースからの参照 | 対象外の場合あり | 接続先ごとに検索 |
| 外部ベンダーの連携処理 | 対象外 | 利用仕様と実行ログ確認 |
SQL Serverのsp_renameやALTER SCHEMA自体には、すべての参照を自動修正する機能はありません。SQL Projectsが更新するのは、プロジェクト内で依存関係を解決できた定義です。(Microsoft Learn)
データベース内の静的な依存関係は、sys.sql_expression_dependenciesでも調査できます。
SELECT
OBJECT_SCHEMA_NAME(referencing_id) AS referencing_schema,
OBJECT_NAME(referencing_id) AS referencing_object,
referenced_schema_name,
referenced_entity_name
FROM sys.sql_expression_dependencies
WHERE referenced_schema_name = N'SalesLT'
AND referenced_entity_name = N'SalesOrderDetail';
ただし、文字列連結で生成される動的SQLや、アプリケーション側から送信されるSQLは、このビューだけでは把握できません。
最低でも、リポジトリ全体で次の表記を検索してください。
SalesOrderDetail
SalesLT.SalesOrderDetail
[SalesLT].[SalesOrderDetail]
コメントやテストコードだけでなく、JSON、YAML、PowerShell、CI/CD設定、ORMマッピングなども検索対象に含めます。
デプロイ前にGenerate Scriptで計画を確認する
SQL Projectsのリファクタリングは、操作した時点ではまだデータベースへ反映されません。
本番へPublishする前に、VS Codeからデプロイスクリプトを生成します。
- Database Projectsビューでプロジェクトを右クリックする
Publishを選択する- 対象サーバーとデータベースを指定する
Generate Scriptを選択する- 生成されたSQLを確認する
- 問題がなければ検証環境へ適用する
- 検証後に本番環境へPublishする
VS CodeのPublish画面では、データベースへ直接反映する前にデプロイスクリプトを生成できます。プロジェクトと対象データベースを比較した結果が反映されるため、単なるビルド成功だけでなく、実際の対象環境に対する処理を確認できます。(Microsoft Learn)
生成スクリプトの確認ポイント
| 確認対象 | 期待する内容 | 危険な兆候 |
|---|---|---|
| テーブル名変更 | sp_rename | DROP TABLEとCREATE TABLE |
| スキーマ移動 | ALTER SCHEMA ... TRANSFER | 新規テーブル作成とデータコピー |
| refactorlog | dbo.__RefactorLogと操作キー | refactorlog由来の処理がない |
| 参照オブジェクト | 新名称への変更 | 旧名称が残っている |
| 権限 | 新しい完全修飾名へのGRANT | 必要な再付与がない |
| データ処理 | 原則として移送処理なし | 大量のINSERT SELECT |
| 削除処理 | 意図したものだけ | 無関係なテーブルや列の削除 |
生成されたSQLでは、次の文字列を検索すると確認しやすくなります。
sp_rename
ALTER SCHEMA
__RefactorLog
DROP TABLE
CREATE TABLE
INSERT INTO
refactorlogが正しくパッケージ化されていれば、生成スクリプト内には操作キーを示すメッセージと、dbo.__RefactorLogへの記録処理が含まれます。(Microsoft Developer Blogs)
BlockOnPossibleDataLossを無効化して解決しない
名前変更を手動編集した結果、データ損失の可能性があるとしてデプロイが停止することがあります。
このとき、次の設定を無効化して強制的に通す方法は推奨できません。
BlockOnPossibleDataLoss=False
BlockOnPossibleDataLossは、データ損失につながる可能性があるスキーマ変更を検出して停止するための安全装置です。既定値はTrueです。(Microsoft Learn)
名前変更でブロックされた場合は、安全装置を外すのではなく、Rename SymbolまたはMove to Schemaを使ってrefactorlogを正しく生成してください。
refactorlogをPre-Deployment Scriptで代用しない
「Pre-Deployment Scriptで先にsp_renameを実行すればよい」と考えるケースがありますが、単純な代用にはなりません。
SQL Projectsでは、Pre-Deployment Scriptが実行される前にデプロイ計画が計算されます。そのため、Pre-Deployment Scriptでテーブル名を変更しても、すでに作成済みのデプロイ計画には変更後の状態が反映されず、後続処理と競合する可能性があります。(Microsoft Learn)
名前変更やスキーマ移動の意図は、Pre-Deployment Scriptではなくrefactorlogを通じてデプロイモデルへ伝えるのが基本です。
Pre-Deployment Scriptは、モデル比較だけでは表現できないデータ準備や、デプロイ前に必要な補助処理へ使います。
データ移動がなくても無停止とは限らない
sp_renameやALTER SCHEMA ... TRANSFERは、大量データのコピーを避けられるため、テーブルを新規作成して全レコードを移す方法より短時間で完了しやすい処理です。
一方で、旧テーブル名を使っているアプリケーションが稼働中の場合、名前変更直後からSQLエラーが発生します。
つまり、次の2点は分けて考える必要があります。
- データを保持したまま変更できるか
- 旧アプリと新アプリを同時に稼働できるか
運用条件ごとの判断基準
| 運用条件 | 推奨する方法 |
|---|---|
| メンテナンス停止が可能 | アプリ停止後に直接リファクタリング |
| DBとアプリを同時更新できる | 同一リリースとして順序を管理 |
| 新旧アプリが一定期間混在する | 旧名のsynonymや互換ビューを検討 |
| 複数の外部システムが直接参照する | すぐに改名せず段階的に廃止 |
| テーブルを直接参照させたくない | ストアドプロシージャを契約層として利用 |
| 24時間稼働で停止できない | Expand-and-Contract方式を検討 |
Microsoftの公式ブログでも、互換性を維持する方法として、ストアドプロシージャによるアクセス契約、旧名称のsynonym、データベースバージョンを使ったアプリ側の分岐などが挙げられています。(Microsoft Developer Blogs)
新旧アプリを併存させる展開例
無停止に近い更新が必要な場合は、次のように段階を分けます。
- 新旧両方のデータベース構成に対応したアプリを先行配信する
- 必要に応じて旧名称のsynonymや互換ビューを用意する
- SQL Projectsからテーブル名やスキーマを変更する
- 新名称を使うアプリへ切り替える
- 実行ログやエラーを監視する
- 旧バージョンがなくなった後に互換レイヤーを削除する
synonymや互換ビューを使う場合は、SELECTだけでなくINSERT、UPDATE、DELETE、権限、ORMの動作まで検証してください。
SQL Projectsのリファクタリングで失敗しやすいポイント
| 失敗例 | 起こり得る問題 | 対策 |
|---|---|---|
| SQL内の名前を直接編集した | 削除と新規作成として認識される | Rename Symbolを使う |
| スキーマ名を直接書き換えた | テーブル再作成や予期しない差分 | Move to Schemaを使う |
| refactorlogをGitへ追加しなかった | CI/CDや別環境で変更意図が消える | SQLファイルと一緒にコミット |
| 過去のrefactorlogを削除した | 未適用環境でデータ損失の可能性 | すべての対象環境への適用状況を確認 |
| XMLをコピーして操作キーを使い回した | 適用済み判定が不正になる | 操作ごとに一意のGUIDを使用 |
| プロジェクト内だけ確認した | アプリやETLが停止する | リポジトリと外部システムを調査 |
| スキーマ移動後の権限を確認しなかった | 利用者やバッチがアクセス不能になる | 権限をプロジェクトで宣言管理 |
| Generate Scriptを省略した | 本番で予期しないDROPが実行される | 対象DBに対する計画を事前確認 |
| Pre-Deployment Scriptだけで改名した | 事前計算済みの計画と競合する | refactorlogを使用 |
| データ損失チェックを無効化した | 本当に危険な変更まで実行される | 原因となる差分を修正 |
Refactorを使わず段階的移行を選ぶべきケース
次のケースでは、単純な名前変更よりも段階的なデータベース移行が適しています。
- 1つのテーブルを複数テーブルへ分割する
- 複数テーブルを統合する
- 主キーやデータ型を大きく変更する
- データの変換やクレンジングが必要
- 外部システムの参照先をすぐに変更できない
- 旧アプリと新アプリを長期間併存させる
- スキーマ変更時のロックを許容できない
- CDC、レプリケーション、監査機能への影響が大きい
この場合は、新しい構造を追加して一定期間併存させ、アプリケーションの切り替え後に旧構造を削除するExpand-and-Contract方式を検討します。
また、ストアドプロシージャ、ビュー、関数、トリガーなどのモジュールは、sp_renameやALTER SCHEMAを使っても定義内の名称が適切に変わらない場合があります。Microsoftも、これらのオブジェクトについては削除と新しい名称での再作成を推奨しています。テーブルや列と同じ感覚で処理せず、生成されたデプロイ計画を個別に確認してください。(Microsoft Learn)
まとめ
SQL Database Projects extension for Visual Studio Codeでテーブル名やスキーマを安全に変更するには、SQL定義を直接書き換えず、VS Codeのリファクタリング機能を使います。
テーブル名や列名はRename Symbol、スキーマ移動はRefactor > Move to Schemaから実行してください。変更内容が.refactorlogへ記録されることで、デプロイ時にはsp_renameまたはALTER SCHEMA ... TRANSFERが生成され、テーブルの再作成や大量のデータ移動を避けられます。
実際の作業では、次の順序で進めるのが安全です。
- プロジェクトと対象データベースの差分を整理する
- VS CodeのRefactorから変更する
.refactorlogをSQLファイルと一緒にコミットする- Generate Scriptで
DROP TABLEがないことを確認する - プロジェクト外の参照とオブジェクト権限を確認する
- 本番相当環境でデプロイを検証する
- アプリケーションとの更新順序を決めて本番へ展開する
refactorlogは単なる履歴ファイルではなく、データを保持したまま変更するためのデプロイ指示です。作成後も削除せず、CI/CDで使用する.dacpacに確実に含めて管理してください。

コメント