从Postgres迁移到SQL Server 2008

14

我需要将一个Postgres 7的数据库迁移到SQL Server 2008中。我熟悉SSIS导入和导出向导,但我不知道如何定义数据源或定义数据提供程序。

什么是将Postgres迁移到SQL Server的最佳方法,以及如何定义Postgres的数据源/驱动程序?


您可以从“数据源”下拉菜单中选择SQL Server Native Client。我猜Postgres需要ODBC提供程序,但我不知道如何实现它。 - reach4thelasers
你目前是如何连接到Postgres的?你还没有设置Postgres的ODBC数据源吗?是的,你需要设置它。 - JohnB
问题1:为什么会有人想要这样做?那样做不仅是经济自杀,也是技术自杀。 - Stefan Steiger
你可以使用我的答案:https://dev59.com/Bmw15IYBdhLWcg3whME1#70241329 - Simin Ghasemi
4个回答

13
我在使用 SQL Server 2008 R2 的导入向导从 PostgreSQL 导入表格时遇到问题。我已经安装了 PostgreSQL ODBC 驱动程序,所以在导入向导中的数据源中选择了“.Net Framework Data Provider for Odbc”,并提供了我的 PostgreSQL 数据库的 DSN 名称。向导成功找到了表格,但当我进行导入时出现了错误:
"无法检索源和目标数据的列信息。 “Billing” -> [dbo]。[Billing]: - 找不到列-1。"
我在 Microsoft 博客文章 here 中找到了解决方案。显然,问题在于各种 ODBC 驱动程序在报告列元数据时使用不同的属性名称。为了让导入工作,我不得不编辑位于以下位置的“ProviderDescriptors.xml”文件:
"C:\Program Files\Microsoft SQL Server\100\DTS\ProviderDescriptors\ProviderDescriptors.xml"
<dtm:ProviderDescriptor SourceType="System.Data.Odbc.OdbcConnection">

...元素我不得不更改属性...

<dtm:ColumnSchemaAttributes
    NameColumnName = "COLUMN_NAME"
    OrdinalPositionColumnName="ORDINAL_POSITION"
    DataTypeColumnName = "TYPE_NAME"
    MaximumLengthColumnName = "COLUMN_SIZE"
    NumericPrecisionColumnName = "COLUMN_SIZE"
    NumericScaleColumnName = "DECIMAL_DIGITS"
    NullableColumnName="NULLABLE"
    NumberOfColumnRestrictions="4"
/>

...到...

<dtm:ColumnSchemaAttributes
    NameColumnName = "COLUMN_NAME"
    OrdinalPositionColumnName="ORDINAL_POSITION"
    DataTypeColumnName = "TYPE_NAME"
    MaximumLengthColumnName = "LENGTH"
    NumericPrecisionColumnName = "PRECISION"
    NumericScaleColumnName = "SCALE"
    NullableColumnName="NULLABLE"
    NumberOfColumnRestrictions="4"
/>

那就是说,我必须调整MaximumLengthColumnNameNumericPrecisionColumnNameNumericScaleColumnName属性值为"LENGTH""PRECISION""SCALE"。一旦这个更改完成,从PostgreSQL到SQL Server的导入就成功了。

1
谢谢您的见解!我从来没有让它工作过! - reach4thelasers
我曾经遇到过同样的问题。ProviderDescriptors.xml 文件存放在 Program Files 和Program Files(x86) 下。通常 SQL Management Studio 是32位的,并且以32位运行DTS向导。所以要在(x86)树中更改该文件。只有在32位的Import/export程序下才能使它正常工作。即使在更改了另一个位置的文件后,64位的Import/Export仍然无法正常工作。 - Derek Wade
4
更新:64位也可以使用,但不要在同一目录下制作文件的“副本”。所有文件(即使没有命名为*.xml)都会被加载并可能覆盖您的更改。 - Derek Wade
这对我有用,非常感谢!我确实复制了@DerekWade,但似乎没有冲突。也许它们按正确的顺序处理了。 - GerardV
删除备份文件(在我的情况下是 ProviderDescriptors.xml~)有所帮助。因此,顺序很重要。 - Vertigo

11

祝你使用SQL Server导入和导出向PostgreSQL导入数据好运。但是,我已经阅读了许多人在使用中遇到困难的留言板帖子,例如:

这是我在此主题上找到的最有用的线程:


为了帮助与我有相似目标的人。在 SQL Server 导入和导出向导的数据源下拉菜单中,不要选择“PostgreSQL OLE DB Provider”,而应选择“.Net Framework Data Provider for Odbc”。

然后,您必须创建一个 DSN 并提供 ConnectionString。以下 ConnectionString 对我有效:

Driver={PostgreSQL};Server=localhost;Port=5432;Database=TestMasterMap;Uid=postgres;Pwd=;

要创建 DSN,您必须进入“管理工具” à “数据源(ODBC)”,并创建用户 DSN。完成后,可以在 SQL Server 导入和导出向导的 DSN 文本框中提供 DSN 名称。


一位评论者声称它起作用了,但他在大表格上遇到了“在读取元组时内存不足”的错误。因此,对于超过 300 万行的表格,他不得不将导入分解成 300 万行的块。

此外,在该线程中还有一个本地的.NET用于PostgreSQL的提供程序链接。

就我个人而言,如果这是我只需要做一次且我相当了解模式和数据的情况下,我会尝试以下步骤:

  1. 将数据从PostgreSQL导出为平面文件
  2. 在SQL Server中创建模式(没有PK或约束)
  3. 使用SSIS导入/导出向导导入平面文件
  4. 然后创建必要的PK和约束

以上步骤可能需要花费的时间比花费数天来处理SSIS导入/导出向导和PostgreSQL更少(但如果这些工具能够正常工作,那将是很好的!)


我刚试图将我的表作为CSV文件导入到SQL Server 2005中,发现CSV导入非常有问题。由于各种问题,我根本无法使其正常工作。PostgreSQL却毫不费力地导入了相同的文件,没有任何问题。 - juzzlin
我喜欢将数据导出到CSV的想法。直接使用SSIS处理对我来说效果不佳,尤其是因为我想要导出的数据是组织在视图中的,而ODBC驱动程序(或者SSIS本身)似乎无法识别它们。 - Andre

1
当我完成上面的回答后,我想尝试 SQL WorkbenchJ;它有一个数据泵功能,对我来说效果非常好。我成功地将我的PostgreSQL数据库中的数据导出到SQL服务器实例中。
那些想要以批处理模式(通过shell)运行此操作的人,请参考 Google Groups Thread。讨论中提到的WbCopy命令在我找到的任何地方都没有得到很好的记录,但您可以通过数据泵界面生成一个,并随时更改所需内容。

0
为了更具体地说明如何实现标记答案中所描述的内容,以下是一个实际示例:您可以从PostgresQL导出到平面文件,然后使用bcp实用程序导入到SQL Server中。 例如,在.bat文件中,对于单个表格(并且您需要在目标SQL数据库中已经创建该表格):
@echo off

set DbName=YOUR_POSTGRES_DB_NAME
set csvpath=C:\PATH_TO_CSV\CSV_NAME.csv
set username=YOUR_POSTGRES_DB_USERNAME

:: Export to CSV, note we're using a ~ delimiter to avoid issues with commas in fields
psql -U %username% -d %DbName% -c "COPY (select * from SOURCE_TABLE_NAME) TO STDOUT (FORMAT CSV, HEADER TRUE, DELIMITER '~', ENCODING 'UTF8');" > %csvpath%

:: Import CSV to SQL Server
set logpath=C:\bcplog.txt
set errorlogpath=C:\bcperrors.txt
set sqlserver=YOUR_SQL_SERVER
set sqldb=YOUR_DB_NAME

:: page code 65001 = UTF-8
bcp DESTINATION_TABLE_NAME IN %csvpath% -t~ -F1 -c -C65001 -S %sqlserver% -d %sqldb% -T -o %logpath% -e %errorlogpath%

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接