web-dev-qa-db-ja.com

PostgreSQLデータベースをSQLServerに移行する方法は?

スキーマとデータの両方で、SQL Serverに移行したいPostgreSQLデータベースがあります。私は貧しいので、お金を払いたくありません。私も怠け者なので、あまり仕事をしたくありません。現在、私はこのテーブルをテーブルごとに実行していますが、実行するテーブルは約100個あります。これは非常に退屈です。

私が望むことを行う何らかのトリックがありますか?

47
Hut8

このServerfaultページの受け入れられた回答でいくつかの有用な情報を見つけることができるはずです: https://serverfault.com/questions/65407/best-tool-to-migrate-a-postgresql-database-to- ms-sql-2005

データなしでスキーマを変換できる場合、次のコマンドを使用してデータの手順を短縮できます。

pg_dump --data-only --column-inserts your_db_name > data_load_script.sql

このロードは非常に遅くなりますが、--column-insertsオプションは、データの各行に対して可能な限り最も一般的なINSERTステートメントを生成し、互換性があるはずです。

編集:スキーマの変換に関する提案は次のとおりです。

スキーマをダンプすることから始めますが、所有権または権限に関係するものはすべて削除します。これで十分です:

pg_dump --schema-only --no-owner --no-privileges your_db_name > schema_create_script.sql

このファイルを編集して、BEGIN TRANSACTION;行を先頭に追加し、ROLLBACK TRANSACTION;を最後に追加します。これで、SQL Serverのクエリウィンドウでロードして実行できます。エラーが発生した場合は、ファイルの最後に移動し、ROLLBACKステートメントを強調表示して実行します(ステートメントが強調表示されている間にF5キーを押します)。

基本的に、スクリプトが正常に実行されるまで、各エラーを解決する必要があります。次に、ROLLBACK TRANSACTIONCOMMIT TRANSACTIONに変更して、最後に1回実行します。

残念ながら、PostgreSQLからSQL Serverへは一度も行ったことがないので、どのエラーが発生するかはわかりません。ただし、問題になると予想されるいくつかの事項(明らかに、完全なリストではありません):

  • PostgreSQLは、SEQUENCEを使用してNOT NULL INTEGERフィールドをDEFAULTにリンクすることにより、フィールドを自動インクリメントします。 SQL Serverでは、これはIDENTITY列ですが、まったく同じものではありません。それらが同等であるかどうかはわかりませんが、元のスキーマが「id」フィールドでいっぱいの場合は、何らかのトラブルが発生する可能性があります。 SQL ServerにCREATE SEQUENCEがあるかどうかはわかりませんので、それらを削除する必要があります。
  • データベース関数/ストアドプロシージャは、RDBMSプラットフォーム間で変換されません。 CREATE FUNCTIONステートメントを削除して、アルゴリズムを手動で変換する必要があります。
  • データファイルのエンコードに注意してください。私はLinuxの人間なので、Windowsでエンコードを確認する方法はわかりませんが、SQL Serverが期待するものがPostgreSQLからインポートするファイルと同じであることを確認する必要があります。 pg_dumpには、特定のエンコーディングを設定できる--encoding=オプションがあります。 Windowsは、PostgreSQLがUTF-8を使用するUnicodeに対して、2バイトのUTF-16エンコードを使用する傾向があることを思い出すようです。 UTF-16出力のため、SQL ServerからPostgreSQLに移行する際に問題が発生したため、調査する価値があります。
  • PostgreSQLデータ型TEXTは、最大長のない単にVARCHARです。 SQL Serverでは、TEXTは...複雑(および非推奨)です。 TEXTとして宣言されている元のスキーマの各フィールドは、適切なSQL Serverデータ型を確認する必要があります。
  • SQL Serverには、UNICODEデータ用の追加のデータ型があります。私は提案をするのに十分なほど詳しくはありません。私はそれが問題かもしれないことを指摘しています。
50
Matthew Wood

これを実現するためのより高速で簡単な方法を見つけました。

まず、テーブル(またはクエリ)を次のようにタブ区切りファイルにコピーします。

_COPY (SELECT siteid, searchdist, listtype, list, sitename, county, street, 
   city, state, Zip, georesult, elevation, lat, lng, wkt, unlocated_bool, 
   id, status, standard_status, date_opened_or_reported, date_closed, 
   notes, list_type_description FROM mlocal) TO 'c:\SQLAzureImportFiles\data_script_mlocal.tsv' NULL E''
_

次に、SQLでテーブルを作成する必要がありますが、これはスキーマを処理しません。スキーマは、フィールドの順序とデータ型がエクスポートされたtsvファイルと一致する必要があります。

最後に、SQLのbcpユーティリティを実行して、tsvファイルを次のように取り込みます。

_bcp MyDb.dbo.mlocal in "\\NEWDBSERVER\SQLAzureImportFiles\data_script_mlocal.tsv" -S tcp:YourDBServer.database.windows.net -U YourUserName -P YourPassword -c
_

私が遭遇したいくつかの注意事項。 PostgresとSQL Serverでは、ブールフィールドの処理が異なります。 SQL Serverスキーマでは、ブールフィールドをvarchar(1)に設定する必要があり、結果のデータは 'f'、 't'またはnullになります。次に、このフィールドをビットに変換する必要があります。次のようなことをする:

_ALTER TABLE mlocal ADD unlocated bit;
UPDATE mlocal SET unlocated=1 WHERE unlocated_bool='t';
UPDATE mlocal SET unlocated=0 WHERE unlocated_bool='f';
ALTER TABLE mlocal DROP COLUMN unlocated_bool;
_

もう1つは、2つのプラットフォーム間で地理/ジオメトリフィールドが大きく異なることです。 ST_AsText(geo)を使用してジオメトリフィールドをWKTとしてエクスポートし、SQL Server側で適切に変換します。

このような調整が必要な非互換性がさらに存在する場合があります。

編集。したがって、この手法は技術的には機能しますが、数百万のレコードを100以上のテーブルからSQL Azureに転送しようとしていますが、bcpからSQL Azureへはかなり不安定です。断続的に取得し続けますBCPホストデータファイルを開けませんエラー、サーバーが断続的にタイムアウトになり、何らかの理由でエラーや問題の兆候なしに一部のレコードが転送されません。したがって、この手法は、大量のデータをAzure SQLに転送するには安定していません。

1
Brad Mathews