跳到正文
IntoSQL 首页

将 PostgreSQL 转换为 SQL Server

拖入由 pg_dump 或 pg_dumpall 生成的纯文本转储(.sql 或 .sql.gz),即可下载包含相同表、键、索引和数据的 SQL Server 脚本。SQL Server 无法原样存储的每个值,以及它不支持的每个对象,都会在报告中列出。

你的文件
sqlshop_2024_postgres.sql示例文件,6.2 kB
你的数据库

已转换 18 行,2 处修正,无拒绝

显示

shop_2024_postgres.sql 中的表PostgreSQL 18.6 转储 · 由 pg_dump 写出 · utf8mb4

  • customers8 行1
    8 列
    idint not null
    namenvarchar(max) not null
    emailnvarchar(450) not null
    countrynvarchar(2) not null
    is_activebit not null
    tagsnvarchar(max) not null
    signed_update
    created_atdatetimeoffset(6) not null
  • orders10 行1
    10 列
    idint not null
    customer_idint not null
    statusnvarchar(9) not null
    totaldecimal(10,2) not null
    itemssmallint not null
    ordered_atdatetime2(6) not null
    shipped_atdatetime2(6)
    notenvarchar(max)
    detailsnvarchar(max)
    deliverynvarchar(100)

未转换

  • 视图 paid_orders

每种数据库都用自己的语言编写这些对象。请为 SQL Server 重写它们。

-- Written by IntoSQL from a PostgreSQL dump. Load it with: sqlcmd -b -f 65001 -d <database> -i <file>
SET NOCOUNT ON;
SET ANSI_NULLS ON;
SET QUOTED_IDENTIFIER ON;
SET ANSI_PADDING ON;
SET ANSI_WARNINGS ON;
SET ARITHABORT ON;
SET CONCAT_NULL_YIELDS_NULL ON;
SET NUMERIC_ROUNDABORT OFF;
GO

CREATE TABLE [dbo].[customers] (
    [id] int IDENTITY(1001, 1) NOT NULL,
    [name] nvarchar(max) COLLATE Latin1_General_100_BIN2 NOT NULL,
    [email] nvarchar(450) COLLATE Latin1_General_100_BIN2 NOT NULL,
    [country] nvarchar(2) COLLATE Latin1_General_100_BIN2 DEFAULT N'US' NOT NULL,
    [is_active] bit DEFAULT 1 NOT NULL,
    [tags] nvarchar(max) COLLATE Latin1_General_100_BIN2 NOT NULL,
    [signed_up] date NULL,
    [created_at] datetimeoffset(6) DEFAULT SYSDATETIMEOFFSET() NOT NULL,
    CONSTRAINT [PK_customers] PRIMARY KEY ([id])
);
GO

CREATE TABLE [dbo].[orders] (
    [id] int IDENTITY(5001, 1) NOT NULL,
    [customer_id] int NOT NULL,
    [status] nvarchar(9) COLLATE Latin1_General_100_BIN2 DEFAULT N'pending' NOT NULL,
    [total] decimal(10,2) NOT NULL,
    [items] smallint DEFAULT 1 NOT NULL,
    [ordered_at] datetime2(6) NOT NULL,
    [shipped_at] datetime2(6) NULL,
    [note] nvarchar(max) COLLATE Latin1_General_100_BIN2 NULL,
    [details] nvarchar(max) COLLATE Latin1_General_100_BIN2 NULL,
    [delivery] nvarchar(100) COLLATE Latin1_General_100_BIN2 NULL,
    CONSTRAINT [CK_orders_status] CHECK ([status] IN (N'pending', N'paid', N'shipped', N'cancelled')),
    CONSTRAINT [orders_total_check] CHECK ([total] >= (0)),
    CONSTRAINT [PK_orders] PRIMARY KEY ([id])
);
GO

SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [tags], [signed_up], [created_at]) VALUES
(1,N'Ana Martínez',N'ana@example.com',N'MX',1,N'["vip"]','2023-01-15','2023-01-15 10:24:00+00:00'),
(2,N'Zoë Müller',N'zoe@example.de',N'DE',1,N'[]','2023-02-03','2023-02-03 08:11:42+00:00'),
(3,N'José Peña',N'jose@example.es',N'ES',0,N'["wholesale","late payer"]','2023-03-21','2023-03-21 19:05:17+00:00'),
(4,N'李雷',N'lilei@example.cn',N'CN',1,N'[]','2023-05-09','2023-05-09 02:40:00+00:00'),
(5,N'Noah O''Brien',N'noah@example.ie',N'IE',1,N'[]',NULL,'2023-06-30 14:00:00+00:00'),
(6,N'Amélie Laurent',N'amelie@example.fr',N'FR',1,N'["vip"]','2024-01-02','2024-01-02 09:30:00+00:00'),
(7,N'Ravi Patel',N'ravi@example.in',N'IN',0,N'[]','2024-02-29','2024-02-29 23:59:59+00:00'),
(8,N'Sofia Rossi 🌻',N'sofia@example.it',N'IT',1,N'[]','2024-04-12','2024-04-12 12:12:12+00:00');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [status], [total], [items], [ordered_at], [shipped_at], [note], [details], [delivery]) VALUES
(1,1,N'shipped',129.90,3,'2024-03-01 10:00:00','2024-03-02 16:30:00',NULL,N'{"gift": false}',N'1 day 06:30:00'),
(2,2,N'paid',54.00,1,'2024-03-02 11:15:00',NULL,N'Gift wrap 🎁',N'{"gift": true, "wrap": "red"}',NULL),
(3,1,N'cancelled',12.50,1,'2024-03-03 09:45:00',NULL,N'Customer changed their mind',NULL,NULL),
(4,4,N'shipped',980.00,12,'2024-03-05 02:10:00','2024-03-07 08:00:00',N'请小心轻放',N'{"fragile": true}',N'2 days 05:50:00'),
(5,5,N'pending',45.75,2,'2024-03-08 17:20:00',NULL,N'Leave at the door; ring twice',NULL,NULL),
(6,6,N'shipped',310.40,5,'2024-03-10 13:00:00','2024-03-11 09:00:00',N'Fragile: "glass"',N'{"fragile": true}',N'20:00:00'),
(7,8,N'paid',76.20,2,'2024-03-11 18:45:00',NULL,NULL,NULL,NULL),
(8,2,N'shipped',19.99,1,'2024-03-12 08:00:00',NULL,N'Shipped date set to infinity by an old import',NULL,NULL),
(9,3,N'shipped',64.00,2,'2024-03-14 15:30:00','2024-03-15 10:00:00',N'Two parcels',N'{"parcels": [1, 2]}',N'18:30:00'),
(10,7,N'paid',1499.00,1,'2024-03-15 21:05:00',NULL,N'C:\Users\ravi\invoice.pdf',NULL,NULL);
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO

-- Indexes, foreign keys, counters and triggers, after the rows.
CREATE UNIQUE INDEX [customers_email_key] ON [dbo].[customers] ([email]);
CREATE INDEX [idx_orders_customer] ON [dbo].[orders] ([customer_id]);
CREATE INDEX [idx_orders_status_date] ON [dbo].[orders] ([status], [ordered_at]);
ALTER TABLE [dbo].[orders] WITH NOCHECK ADD CONSTRAINT [orders_customer_id_fkey] FOREIGN KEY ([customer_id]) REFERENCES [dbo].[customers] ([id]);
BEGIN TRY ALTER TABLE [dbo].[orders] WITH CHECK CHECK CONSTRAINT [orders_customer_id_fkey]; END TRY BEGIN CATCH PRINT N'Foreign key ' + N'[orders_customer_id_fkey]' + N' has rows without a parent: it stays unchecked, and new rows are checked.'; END CATCH;
DECLARE @next decimal(38,0) = (SELECT MAX([id]) FROM [dbo].[customers]); IF @next IS NOT NULL BEGIN IF @next < 1000 SET @next = 1000; DBCC CHECKIDENT (N'[dbo].[customers]', RESEED, @next) WITH NO_INFOMSGS; END;
GO
EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = N'People who bought at least once', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'customers';
DECLARE @next decimal(38,0) = (SELECT MAX([id]) FROM [dbo].[orders]); IF @next IS NOT NULL BEGIN IF @next < 5000 SET @next = 5000; DBCC CHECKIDENT (N'[dbo].[orders]', RESEED, @next) WITH NO_INFOMSGS; END;
GO
GO

修正

  1. customers 的 "tags" 是 text[],SQL Server 没有该类型,因此为 nvarchar(max),值保持不变。
  2. orders 的 "delivery" 是 interval,SQL Server 没有该类型,因此为 nvarchar(100),值保持不变。

需要检查

  • 1 个视图、触发器、例程或事件未转换;报告逐一列出了它们。 请在 SQL Server 中手动重新创建它们。
  • customers 中 "tags" 的默认值无法为 SQL Server 写出(a value its type can't hold),因此该列没有默认值。 如果新行需要,请手动添加默认值。
  • orders 上的索引 idx_orders_details 使用了无法为 SQL Server 写出的表达式(an index on an expression),因此未创建。 如果查询需要,请手动创建该索引。
  • orders 的 "shipped_at" 中有 1 个值是 SQL Server 无法存储的日期,例如 infinity,因此设为 NULL。 SQL Server 存储 1 到 9999 年,不支持无穷值;如果这些日期很重要,请在源数据中替换它们。

文件在这台电脑上转换,永远不会上传。

其他示例:

从 PostgreSQL 到 SQL Server 的变化

每一行是转换器应用的一条规则,以及该规则更改你的数据时在报告中写入的记录。

  • boolean

    bit

    bit 将 true 存为 1,false 存为 0。

  • varchar(n), char(n), text

    nvarchar(n);text 为 nvarchar(max),用于键且所有值都能容纳时为 nvarchar(450)

    nvarchar 可容纳每个字符。SQL Server 无法为 nvarchar(max) 建立索引,因此键中的文本按键能容纳的长度设定。

  • text comparison

    精确比较 (Latin1_General_100_BIN2);citext 不区分大小写 (Latin1_General_100_CI_AS_SC)

    SQL Server 常用的排序规则不区分大小写,而 PostgreSQL 的文本区分,因此每列都声明其比较方式,唯一键能像原来一样区分各行。

  • numeric(p,s) past 38 digits; numeric without a precision

    nvarchar;值不超过 38 位时为按值调整的 decimal(p,s)

    SQL Server 的 decimal 可容纳 38 位数字。不带精度的 numeric 获得能容纳其值的最窄 decimal;更宽的数字保存为文本,使每一位都保持精确。

    报告记录: decimal_as_text

  • money

    decimal(19,2)

    SQL Server 的 money 比 PostgreSQL 的小,且有四位小数;decimal(19,2) 可容纳每个金额,不带服务器区域设置添加的货币符号。

    报告记录: type_replaced

  • interval

    nvarchar(100),存放 PostgreSQL 的文本

    SQL Server 没有 interval 类型;文本保留每个部分。

    报告记录: type_replaced

  • arrays (integer[], text[]...)

    存放 JSON 数组的 nvarchar(max)

    SQL Server 没有数组。JSON 数组保留每个元素和 NULL,OPENJSON 可以读取它。

    报告记录: type_replaced

  • ranges, geometric types, tsvector, xml, hstore, PostGIS, composite and extension types

    nvarchar(max),存放 PostgreSQL 的文本

    SQL Server 没有对应的类型,因此每个值保留 PostgreSQL 写出的文本。

    报告记录: type_replaced

  • json, jsonb

    nvarchar(max)

    SQL Server 的 JSON 函数从文本读取 JSON。

  • timestamp

    datetime2

    不带时区的 timestamp 是挂钟读数,与 datetime2 相同。

  • timestamp with time zone

    UTC 的 datetimeoffset

    datetimeoffset 保留时间点;每个值以 UTC 写入,无论转储写入的偏移量是多少,都是同一时刻。

  • time with 24:00:00 in it

    nvarchar(17)

    SQL Server 的 time 止于 23:59:59.9999999,因此包含 24:00:00 的列保留其文本。

    报告记录: time_as_interval

  • infinity, -infinity and BC dates

    NULL

    SQL Server 存储 1 到 9999 年,不支持无穷值。这些值变为 NULL,报告会统计其数量。

    报告记录: date_out_of_range

  • NaN and Infinity in numeric, real and double precision

    NULL

    SQL Server 的数字没有 NaN 或 Infinity,因此这些值变为 NULL,报告会统计其数量。

    报告记录: invalid_value_null

  • NOT NULL columns with values that become NULL

    去除 NOT NULL

    值必须变为 NULL 的列无法保留 NOT NULL,否则导入会中止。

    报告记录: not_null_relaxed

  • enum types

    nvarchar,并带有限定其标签的 CHECK

    带检查约束的文本保留相同的值。

  • enum columns holding values outside their labels

    不加检查约束的 nvarchar

    标签之外的值会使检查失败,因此不创建检查约束。

    报告记录: enum_check_skipped

  • uuid, inet, cidr, macaddr

    uniqueidentifier;地址为 nvarchar

    uniqueidentifier 是 SQL Server 的 UUID;地址保存为文本。

  • bytea

    varbinary(max)

    字节仍然是字节。

  • bit(n), bit varying

    一位时为 bit;不超过 63 位时为 bigint;更长则为文本数字

    单个位表示是或否;更长的位串存储为其各位组成的数字。

  • oid, xid, cid

    bigint,并带有不能为负数的 CHECK

    bigint 可容纳每个值。

  • serial, identity

    IDENTITY,从最大的 id 之后继续

    复制过来的 id 以 IDENTITY_INSERT 导入,计数器从最大的 id 或序列的下一个值之后继续,取两者中较大者。

  • a second serial or identity column in a table

    普通整数

    SQL Server 每个表只有一个 IDENTITY 列计数;其他列保留其值,不带计数器。

    报告记录: counter_dropped

  • sequences not owned by a column

    CREATE SEQUENCE ... AS bigint,带下一个值

    SQL Server 有选项相同的序列;每个序列从转储停下的位置继续。

  • generated columns

    计算列,源数据存储它们时为 PERSISTED

    SQL Server 以相同的两种方式计算它们。

  • generated columns with functions SQL Server lacks

    带有这些值的普通列

    无法为 SQL Server 写出的公式会留下一个带有转储中值的普通列和一条报告记录。

    报告记录: generated_not_translated

  • defaults with functions SQL Server lacks, and defaults from a sequence

    无默认值

    无法为 SQL Server 写出的默认值会被省略,并在报告中列出。

    报告记录: default_not_translated

  • CHECK constraints

    已转换,内联在 CREATE TABLE 中

    内联的检查约束在每行导入时检验。

  • CHECK constraints with functions SQL Server lacks

    不创建

    无法为 SQL Server 写出的检查约束会被省略,并在报告中列出。

    报告记录: check_skipped

  • CHECK ... NOT VALID

    不创建

    PostgreSQL 从未检查之前已有的行,因此它们可能违反该约束。

    报告记录: check_not_valid

  • gin, gist, brin and hash indexes, partial and expression indexes, and indexes on text that doesn't fit a key

    不创建

    SQL Server 为列建立索引,不为表达式或 nvarchar(max) 建立索引。

    报告记录: index_skipped

  • foreign keys

    在数据之后以 WITH NOCHECK 添加,然后检查,有孤立行时给出警告

    外键在行之后创建,最后检查;有孤立行时外键保持未检查状态并给出警告,而不是中止导入。

  • ON DELETE or ON UPDATE that cascades in a cycle or along a second path

    NO ACTION

    SQL Server 拒绝可能两次到达同一个表的级联操作;PostgreSQL 允许。

    报告记录: foreign_key_action_dropped

  • foreign keys to tables the dump doesn't create

    不创建

    外键无法引用不存在的表。

    报告记录: foreign_key_skipped

  • partitioned tables

    单个表,包含每个分区的行

    行保持不变;如有需要,请在 SQL Server 中重新对该表分区。

    报告记录: partitions_dropped

  • views, functions, procedures, triggers, rules, policies, extensions and types

    在报告中列出

    它们的代码用 PostgreSQL 的语言编写,因此会列出来,由你重新创建。

    报告记录: not_converted_objects

  • dumps without CREATE TABLE (--data-only)

    根据值推断类型

    只含数据的转储只有行,因此类型来自值。

    报告记录: no_schema

  • expressions in INSERT values

    NULL

    不运行数据库的转换器无法对它们求值。

    报告记录: expression_value

  • types IntoSQL doesn't know

    nvarchar(max)

    文本可以容纳任何值;请在导入后更改类型。

    报告记录: unknown_type

  • text that isn't valid in its encoding

    错误的字节变为替换字符

    nvarchar 存储 Unicode 文本。

    报告记录: invalid_utf8_replaced

  • text decoded twice (ñ)

    按原样复制

    转储中存储的正是这些字符,因此按原样复制;报告会指出它们。

    报告记录: mojibake_suspected

在 PostgreSQL 中在 SQL Server 中报告记录
booleanbitbit 将 true 存为 1,false 存为 0。
varchar(n), char(n), textnvarchar(n);text 为 nvarchar(max),用于键且所有值都能容纳时为 nvarchar(450)nvarchar 可容纳每个字符。SQL Server 无法为 nvarchar(max) 建立索引,因此键中的文本按键能容纳的长度设定。
text comparison精确比较 (Latin1_General_100_BIN2);citext 不区分大小写 (Latin1_General_100_CI_AS_SC)SQL Server 常用的排序规则不区分大小写,而 PostgreSQL 的文本区分,因此每列都声明其比较方式,唯一键能像原来一样区分各行。
numeric(p,s) past 38 digits; numeric without a precisionnvarchar;值不超过 38 位时为按值调整的 decimal(p,s)SQL Server 的 decimal 可容纳 38 位数字。不带精度的 numeric 获得能容纳其值的最窄 decimal;更宽的数字保存为文本,使每一位都保持精确。decimal_as_text
moneydecimal(19,2)SQL Server 的 money 比 PostgreSQL 的小,且有四位小数;decimal(19,2) 可容纳每个金额,不带服务器区域设置添加的货币符号。type_replaced
intervalnvarchar(100),存放 PostgreSQL 的文本SQL Server 没有 interval 类型;文本保留每个部分。type_replaced
arrays (integer[], text[]...)存放 JSON 数组的 nvarchar(max)SQL Server 没有数组。JSON 数组保留每个元素和 NULL,OPENJSON 可以读取它。type_replaced
ranges, geometric types, tsvector, xml, hstore, PostGIS, composite and extension typesnvarchar(max),存放 PostgreSQL 的文本SQL Server 没有对应的类型,因此每个值保留 PostgreSQL 写出的文本。type_replaced
json, jsonbnvarchar(max)SQL Server 的 JSON 函数从文本读取 JSON。
timestampdatetime2不带时区的 timestamp 是挂钟读数,与 datetime2 相同。
timestamp with time zoneUTC 的 datetimeoffsetdatetimeoffset 保留时间点;每个值以 UTC 写入,无论转储写入的偏移量是多少,都是同一时刻。
time with 24:00:00 in itnvarchar(17)SQL Server 的 time 止于 23:59:59.9999999,因此包含 24:00:00 的列保留其文本。time_as_interval
infinity, -infinity and BC datesNULLSQL Server 存储 1 到 9999 年,不支持无穷值。这些值变为 NULL,报告会统计其数量。date_out_of_range
NaN and Infinity in numeric, real and double precisionNULLSQL Server 的数字没有 NaN 或 Infinity,因此这些值变为 NULL,报告会统计其数量。invalid_value_null
NOT NULL columns with values that become NULL去除 NOT NULL值必须变为 NULL 的列无法保留 NOT NULL,否则导入会中止。not_null_relaxed
enum typesnvarchar,并带有限定其标签的 CHECK带检查约束的文本保留相同的值。
enum columns holding values outside their labels不加检查约束的 nvarchar标签之外的值会使检查失败,因此不创建检查约束。enum_check_skipped
uuid, inet, cidr, macaddruniqueidentifier;地址为 nvarcharuniqueidentifier 是 SQL Server 的 UUID;地址保存为文本。
byteavarbinary(max)字节仍然是字节。
bit(n), bit varying一位时为 bit;不超过 63 位时为 bigint;更长则为文本数字单个位表示是或否;更长的位串存储为其各位组成的数字。
oid, xid, cidbigint,并带有不能为负数的 CHECKbigint 可容纳每个值。
serial, identityIDENTITY,从最大的 id 之后继续复制过来的 id 以 IDENTITY_INSERT 导入,计数器从最大的 id 或序列的下一个值之后继续,取两者中较大者。
a second serial or identity column in a table普通整数SQL Server 每个表只有一个 IDENTITY 列计数;其他列保留其值,不带计数器。counter_dropped
sequences not owned by a columnCREATE SEQUENCE ... AS bigint,带下一个值SQL Server 有选项相同的序列;每个序列从转储停下的位置继续。
generated columns计算列,源数据存储它们时为 PERSISTEDSQL Server 以相同的两种方式计算它们。
generated columns with functions SQL Server lacks带有这些值的普通列无法为 SQL Server 写出的公式会留下一个带有转储中值的普通列和一条报告记录。generated_not_translated
defaults with functions SQL Server lacks, and defaults from a sequence无默认值无法为 SQL Server 写出的默认值会被省略,并在报告中列出。default_not_translated
CHECK constraints已转换,内联在 CREATE TABLE 中内联的检查约束在每行导入时检验。
CHECK constraints with functions SQL Server lacks不创建无法为 SQL Server 写出的检查约束会被省略,并在报告中列出。check_skipped
CHECK ... NOT VALID不创建PostgreSQL 从未检查之前已有的行,因此它们可能违反该约束。check_not_valid
gin, gist, brin and hash indexes, partial and expression indexes, and indexes on text that doesn't fit a key不创建SQL Server 为列建立索引,不为表达式或 nvarchar(max) 建立索引。index_skipped
foreign keys在数据之后以 WITH NOCHECK 添加,然后检查,有孤立行时给出警告外键在行之后创建,最后检查;有孤立行时外键保持未检查状态并给出警告,而不是中止导入。
ON DELETE or ON UPDATE that cascades in a cycle or along a second pathNO ACTIONSQL Server 拒绝可能两次到达同一个表的级联操作;PostgreSQL 允许。foreign_key_action_dropped
foreign keys to tables the dump doesn't create不创建外键无法引用不存在的表。foreign_key_skipped
partitioned tables单个表,包含每个分区的行行保持不变;如有需要,请在 SQL Server 中重新对该表分区。partitions_dropped
views, functions, procedures, triggers, rules, policies, extensions and types在报告中列出它们的代码用 PostgreSQL 的语言编写,因此会列出来,由你重新创建。not_converted_objects
dumps without CREATE TABLE (--data-only)根据值推断类型只含数据的转储只有行,因此类型来自值。no_schema
expressions in INSERT valuesNULL不运行数据库的转换器无法对它们求值。expression_value
types IntoSQL doesn't knownvarchar(max)文本可以容纳任何值;请在导入后更改类型。unknown_type
text that isn't valid in its encoding错误的字节变为替换字符nvarchar 存储 Unicode 文本。invalid_utf8_replaced
text decoded twice (ñ)按原样复制转储中存储的正是这些字符,因此按原样复制;报告会指出它们。mojibake_suspected

将脚本导入 SQL Server

脚本先创建表、复制行,再添加键、索引和外键,因此导入速度快,并会在遇到第一个错误时停止。

sqlcmd -b -f 65001 -S localhost -d mydb -i postgresql.sql_server.sql

外键先以 WITH NOCHECK 添加,然后再检查。如果某行指向不存在的行,脚本会说明是哪个约束,并让它保持未检查状态,而不是中途失败。

对于较大的转储,请在服务器所在的机器上运行 sqlcmd。每批最多 1000 行单独提交,因此事务日志保持较小。

如何转储 PostgreSQL 以获得最佳结果

转换器读取转储中的内容。以下选项能让转储保留更多数据:

  • --format=plain 是 pg_dump 的默认格式,写出 SQL。custom 或 directory 归档(-Fc、-Fd)可用 pg_restore -f dump.sql 转为 SQL,无需数据库服务器。
  • --no-owner --no-privileges 会省略角色和授权,转换器本来也会跳过它们,因此转储更小。
  • pg_dumpall 将每个数据库转储到一个文件中;每个数据库的表名前会加上该数据库名,因此不会冲突。

哪些内容不会转换

视图、物化视图、函数、存储过程、触发器、规则、行安全策略、扩展和类型都是用 PostgreSQL 自己的语言编写的。它们会按名称在报告中列出,绝不会被悄悄丢弃,以便你为 SQL Server 重写。

关于 PostgreSQL 转 SQL Server 的问题

这里没有你要的答案?请通过联系页面给我们留言,会有专人回复。 联系页面

我的转储会被上传吗?

不会。转换器在你的浏览器中运行,分块从磁盘读取转储,因此转储不会离开你的电脑。桌面应用和命令行也在你的电脑上转换。

转储可以多大?

转换器从不把整个转储放进内存:它按范围读取文件两次,边读边写出脚本。几 GB 的转储可以在浏览器、桌面应用和命令行中转换。

它能读取 pg_dump -Fc 归档吗?

不能直接读取:custom 归档是二进制格式。pg_restore -f dump.sql dump.backup 会将其转为转换器读取的纯 SQL,无需连接服务器。转换器收到归档时会给出提示。

转储可以来自哪些 PostgreSQL 版本?

由 PostgreSQL 10 及更高版本的 pg_dump 和 pg_dumpall 写出的转储,行可以是 COPY 或 INSERT。每个测试转储都来自 PostgreSQL 13 和 18,并与其源数据逐个单元格比较。

serial 和标识列的值会保留吗?

会。每个表的 serial 或标识列变为 IDENTITY 列,每行保留其 id,下一个 id 从最大的 id 之后继续。SQL Server 每个表只为一列计数,因此其他列保留其值,不带计数器。

数组、enum 和其他 PostgreSQL 类型会怎样处理?

数组变为 JSON 数组,布尔值变为 bit,uuid 变为 uniqueidentifier,带时区的时间戳变为 datetimeoffset。文本像在 PostgreSQL 中一样精确比较,citext 则不区分大小写。range、几何类型和复合类型保留 PostgreSQL 的文本。

函数、触发器和视图怎么处理?

它们会按名称在报告中列出,但不会转换,因为每种数据库都用自己的语言编写它们。

脚本可以导入哪些 SQL Server 版本?

SQL Server 2017 到 2025。同一个脚本在每个版本上都能导入,如有问题会在第一个错误处停止。