SQL Serverの運用において、「開発環境や移行先のSQL Serverのバージョンが古い(例:SQL Server 2016)」一方で、「本番環境や手元の環境のバージョンが新しい(例:SQL Server 2022)」というケースは珍しくありません。しかし、SQL Serverでは上位互換性はサポートされておらず、上位バージョンのバックアップ(.bak)を下位バージョンに直接復元することはできません。
本記事では、この制限が発生する理由と、それを乗り越えてデータをダウングレード移行・復元するための3つの代表的な代替手段を解説します。
1. バックアップ (.bak) ファイルのリストアが失敗する理由
SQL Serverは下位互換性を重視して設計されています。例えば、SQL Server 2016で作成したバックアップファイルをSQL Server 2022へ復元することは標準でサポートされています。しかし、逆の上位互換性(新しいバージョンから古いバージョンへ)は物理構造の違いからサポートされていません。
SQL Serverのデータベースには内部バージョン番号(内部データベースバージョン)が存在します。
- SQL Server 2022:内部バージョン 957
- SQL Server 2016:内部バージョン 852
SQL Server 2016 (852) は、自分より新しい内部バージョン 957 のデータベースファイルの構造を解釈できないため、バックアップファイルをリストアしようとしたり、MDF/LDFファイルを直接アタッチしようとしたりすると、以下のようなエラーが発生して失敗します。
エラーメッセージの例:
データベース 'DatabaseName' はバージョン 957 ですが、このサーバーはバージョン 852 以前をサポートしています。このデータベースは復元またはアタッチできません。
※データベースの「互換性レベル」を「130(SQL Server 2016)」に下げていても、物理ファイルの内部バージョン自体は移行元の 957 のままになるため、やはりバックアップ復元はできません。
2. 代替手段①:SSMS「スクリプトの生成」ウィザード
最も手軽で標準的な手段は、SQL Server Management Studio (SSMS) を使用して、テーブル構造(スキーマ)と格納されているデータをインサート文のスクリプトとして出力し、移行先で実行する方法です。小〜中規模(数十万レコード程度まで)のデータベースに最適です。
実行手順
- 移行元(2022)のデータベースを右クリックし、[タスク] > [スクリプトの生成] を選択します。
- スクリプトを作成するオブジェクト(通常はデータベース全体、または特定のテーブル)を選択します。
- 「スクリプトの保存または公開」画面で [詳細設定] ボタンをクリックします。
- 詳細設定の中で、以下の2項目を必ず変更します。
- データベースエンジンの種類に対するスクリプト: 移行先のバージョン(例:
SQL Server 2016)に設定 - スクリプトを作成するデータの種類:
スキーマとデータに設定
- データベースエンジンの種類に対するスクリプト: 移行先のバージョン(例:
- 出力されたSQLファイルを、移行先(2016)のSSMSで接続して実行します。
メリット・デメリット
- メリット: SSMSだけで完結し、トリガーやインデックス、外部キーなどの関連情報も自動でスクリプト化されます。
- デメリット: データ量が大きい(数GB以上)場合、生成されるSQLファイルのサイズが極端に巨大化し、移行先で開こうとした際にSSMSがメモリ不足(Out of Memory)でフリーズする原因になります(この場合は
sqlcmdコマンドラインツールで実行するか、別の手段を取る必要があります)。
3. 代替手段②:BACPAC(データ層アプリケーション)のインポート/エクスポート
BACPACは、スキーマ定義(XML形式)とデータ(BACPAC形式)をパッケージ化した1つのファイル(.bacpac)として出力・移行する機能です。Azure SQL Databaseへの移行などで広く使われますが、オンプレミス間での移行でも有効です。
実行手順
- 移行元(2022)のデータベースを右クリックし、[タスク] > [データ層アプリケーションのエクスポート] を選択します。
- 出力先(.bacpacファイル)を指定して実行します。
- 移行先(2016)のオブジェクトエクスプローラーで [データベース] フォルダを右クリックし、[データ層アプリケーションのインポート] を選択します。
- 作成した.bacpacファイルを指定し、インポートを実行します。
注意点
- エクスポート時にスキーマチェックが厳密に行われるため、2022でしか使えないスキーマや構文(新しい計算列など)が存在する場合、エクスポート処理そのものがエラーで停止します。この場合は、移行元のスキーマをあらかじめクリーンアップする必要があります。
4. 代替手段③:インポートおよびエクスポート ウィザード (SSIS)
データ量が非常に大きい(数百万レコード以上)場合には、データ転送のパフォーマンスが高い「インポートおよびエクスポートウィザード」が推奨されます。
実行手順
- あらかじめ移行先(2016)にテーブルの構造(スキーマのみ)を作成しておきます。(上記「スクリプトの生成」で「スキーマのみ」を出力して実行しておくと簡単です)。
- 移行元(2022)のデータベースを右クリックし、[タスク] > [データのエクスポート] を選択します。
- データソースに「移行元のSQL Server」を設定し、変換先に「移行先(2016)のSQL Server」を設定します。
- コピーするテーブルを選択し、必要に応じてマッピング情報を調整した上で、データコピーを実行します。
メリット
- データ転送速度が非常に速く、メモリ制限にかかりにくいため、大規模なデータ移行に向いています。また、外部キー制約やトリガーなどの依存関係を一時的に考慮せずにデータだけを流し込むことができるため、順序依存のエラーが防げます。
5. SQL Server 2022から2016への移行時の注意点
上位から下位への移行においては、下位バージョンでサポートされていない機能が移行元で使われている場合にエラーが発生します。特に 2022 から 2016 への移行では以下の点に注意してください。
- 新機能や関数の使用制限: SQL Server 2022で追加された新しいT-SQL関数(例:
GREATEST,LEAST,STRING_SPLITの第3引数など)を使用しているストアドプロシージャやビュー、計算列が存在する場合、2016で実行すると「オブジェクト名が無効」または構文エラーになります。 - JSONサポート: SQL Server 2016でもJSONの基本機能(
JSON_VALUEなど)は利用できますが、2022で追加された新しいJSON関数(JSON_OBJECT,JSON_ARRAYなど)は使えません。 - ページ・行圧縮機能: SQL Server 2016では、圧縮機能(Page/Row Compression)がEnterpriseエディション専用でしたが、2016 SP1以降であればStandardエディションでも利用可能になっています。移行先サーバーのService Pack適用状況に注意してください。
6. まとめ
SQL Serverの上位から下位への移行では、データ規模や移行環境に合わせて最適な方法を選ぶことが重要です。
- 数万〜数十万行程度(小〜中規模): 簡単な [スクリプトの生成(スキーマとデータ)] を選択。
- クラウドや複数DBへの展開がある場合: 標準化された [BACPACのエクスポート/インポート] を選択。
- 数百万行以上(大規模): 空のスキーマを作成した後に [インポートおよびエクスポートウィザード(エクスポート)] を選択。
移行先のバージョンで非推奨となった機能やサポート外の構文がないか、移行前にスキーマを念入りにチェックしましょう。