PostgreSQL 中与 SQL Server 的 NVARCHAR 相对应的数据类型是什么?

76
如果我在 Microsoft SQL Server 数据库中有 NVARCHAR(或 NTEXT)数据类型的字段,那么在 PostgreSQL 数据库中对应的数据类型是什么?

2
请不要假设每个人都知道 MS SQL 中的“NVARCHAR/NTEXT”是什么。如果您想获取真正的信息,您必须提供更多信息 - 这种数据类型是什么。我个人不知道这种数据类型是什么,它可以存储什么(文本,我猜),它的限制是什么等等。 - user80168
@depesz - 抱歉,它们是Unicode字符字符串。请参见http://msdn.microsoft.com/en-us/library/aa258271(SQL.80).aspx获取定义。 - kevinw
5个回答

53

我非常确定Postgres的varchar与Oracle/Sybase/MSSQL的nvarchar相同,尽管手册中没有明确说明:

http://www.postgresql.org/docs/7.4/static/datatype-character.html

编码转换函数在这里:

http://www.postgresql.org/docs/current/static/functions-string.html http://www.postgresql.org/docs/current/static/functions-string.html#CONVERSION-NAMES

例子:

create table
nvctest (
utf8fld varchar(12)
);
insert into nvctest
select convert('PostgreSQL' using ascii_to_utf_8);
select * from nvctest;

此外,PostgreSQL的一位代表在这篇回答中也有类似的问题:

只要你正确安装了PostgreSQL,我们所有的TEXT数据类型都支持多字节。
这包括:TEXT(推荐),VARCHAR和CHAR。


1
这个答案是错误的。 请在浏览器控制台中尝试以下代码:o = JSON.parse('{ "a": "\\uD83D", "b": "\\uDE01" }'); o.a + o.b然后尝试将单独的属性o.a和o.b存储到Postgres TEXT/VARCHAR和SQLServer NVARCHAR中。检索它们(或在数据库中连接它们)并检查结果。多字节能力并不意味着能够存储半代理对,因为Postgres仅提供UTF-8字符集。请参见下面的详细帖子。 - user6649841

24
简短回答:PostgreSQL中没有SQL Server NVARCHAR的等效类型。 不同数据库上NVARCHAR(N)类型不相等。标准允许使用各种字符排序和编码/字符集。在处理Unicode时,PostgreSQL和SQLServer属于不同阵营,不存在等效性。 这些方面存在差异: 1. 长度语义 2. 可表示内容 3. 排序方式 4. 填充语义 因此,将数据从一个DB系统(或编码/字符集)移动到另一个DB系统可能会导致截断/内容丢失。 具体而言,在PostgreSQL(9.1)字符类型和SQL Server NVARCHAR之间不存在等效性。 您可以将数据迁移到PostgreSQL二进制类型,但将失去文本查询功能。 (除非PostgreSQL开始支持基于UTF-16的Unicode字符集) 长度语义为:

根据数据库和编码,N的解释不同(字符、字节、2*N=字节)。

Microsoft SQL Server使用UCS2编码,其中VARCHAR长度被解释为UCS-2点,即长度*2=字节长度 (https://learn.microsoft.com/en-us/sql/t-sql/data-types/nchar-and-nvarchar-transact-sql?view=sql-server-2017):
他们的NVARCHAR(1)可以存储1个UCS2字符(2个字节的UCS2)。 Oracle UTF编码具有相同的语义(和内部CESU-8存储)。

Postgres 9.1仅具有Unicode UTF-8字符集(https://www.postgresql.org/docs/9.1/multibyte.html),就像 Oracle(在AL32UTF8或AL16UTF16编码中)可以存储1个完整的UCS32代码点。这可能高达4个字节(例如请参见 http://www.oracletutorial.com/oracle-basics/oracle-nvarchar2/明确说明NVARCHAR2(50)列最多可能占用200个字节)。

当处理基本多语言平面(BMP)之外的字符时,差异变得显著。在utf8 ucs32中,这些字符计为一个“char unit”,例如go、char、char32_t和PostgreSQL等。但在UTF-16中,它们表示为代理对,计为两个单位,例如Java、Javascript、C#、ABAP、wchar_t和SQLServer等。

例如,U+1F60A SMILING FACE WITH SMILING EYES将使用SQL Server NVARCHAR(2)中的所有空间。但在PostgreSQL中仅占用一个字符单元。

经典的企业级数据库至少提供了类似于UTF-16的选择(如SAP HANA(CESU-8)、DB 2 with collation、SQL Anywhere(CESU8BIN)等)。 例如,Oracle还提供了他们误导性地称为UTF-8 Collation的选项,实际上是CESU-8。 这具有与UTF-16相同的长度语义、可表示内容(=Microsoft SQL Server)以及适用于基于UTF-16的企业系统(例如SAP R/3)或在Java应用服务器下使用的合适排序。

请注意,一些数据库可能仍将NVARCHAR(N)解释为字节限制长度,即使使用了可变长度的unicode编码(例如SAP IQ的示例)。

  1. 无法表示的内容

UTF-16/CESU-8系统可以表示半代理对,而UTF-8/UTF-32系统则不能。这种内容在此字符集中是无法表示的,但在基于UTF-16的企业系统中经常出现(例如,Windows路径名可能包含此类非UTF-8可表示字符,请参见https://github.com/rust-lang/rust/issues/12056)。因此,UTF-16是UTF-8/UTF-16的“超集”,在处理基于此编码的企业/操作系统数据时通常是一个重要标准(SAP、Windows、Java、JavaScript)。请注意,Javascript JSON编码特别注意能够表示这些字符(https://www.rfc-editor.org/rfc/rfc8259#page-10)。
(2)和(3)在迁移查询时更为相关,但不适用于数据迁移。
3. 二进制排序:
请注意,CESU-8/UTF-16的二进制排序顺序与UTF-8/UTF-32不同。
UTF-16/CESU-8/Java/JavaScript/ABAP排序顺序:
U+0041  LATIN CAPITAL LETTER A
U+1F60A SMILING FACE WITH SMILING EYES
U+FB03  LATIN SMALL LIGATURE ffi 

UTF-8 / UCS-32 (go)排序顺序:

U+0041  LATIN CAPITAL LETTER A
U+FB03  LATIN SMALL LIGATURE ffi 
U+1F60A SMILING FACE WITH SMILING EYES
  1. 填充语义

填充语义在数据库中有所不同,特别是在比较VARCHAR和CHAR内容时。


我看到有人提到未配对的代理项不被视为“有效”的UTF-16。但这并不能解决问题,因为大多数接受UTF-16的数据库在存储之前并不验证UTF-16;接受“未经验证的UTF-16”(或者我见过的称为WTF-16)仍然会导致UTF-8中无法表示的内容。 - undefined

13

如果你的数据库采用UNICODE编码,那么数据类型应该是varchartext。如果你的数据库采用非UNICODE编码,那么没有特别的数据类型可以给你一个unicode字符串——你可以将其存储为bytea流,但那不会是字符串。


8

标准的TEXT数据类型对于IT技术来说完全足够。


2

Necromancing - 什么鬼,自2009年以来都没有真正的答案?
nvarchar 的 PostgreSQL 等效方式是

national character varying(length) 

顺便说一句,这是SQL标准的一部分,并且在SQL服务器上也适用。

顺便说一句,对于nvarchar(MAX),PostgreSQL的等效语句是

national character varying 

如果在您的版本中nvarchar与postgresql不兼容,您可以创建一个域(domain)。
CREATE DOMAIN datetime AS timestamp without time zone; 
CREATE DOMAIN nvarchar AS national character varying; 
CREATE DOMAIN uniqueidentifier AS uuid; 

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