Oracle和SQL Server中NVARCHAR的区别是什么?

23
我们正在将一些数据从SQL Server迁移到Oracle。对于在SQL Server中定义为的列,我们开始在Oracle中创建列,认为它们是相似的。但看起来它们并不相同。
我阅读了StackOverflow上的几篇文章,并想确认我的发现。
如果数据库字符集为AL32UTF8(对我们来说是正确的),则Oracle VARCHAR2已经支持Unicode。
SQLServer不支持Unicode。 SQLServer明确要求列以NCHAR / NVARCHAR类型存储Unicode数据(特别是使用2字节UCS-2格式)。
因此,可以/应该说SQL Server NVARCHAR列可以迁移到Oracle VARCHAR2列吗?

1
微软确认了Oracle NVARCHAR2 <==> SQLServer NVARCHAR的对应关系。但我想确认的是Oracle VARCHAR2 <==> SQLServer NVARCHAR的对应关系?(因为Oracle VARCHAR2已经准备好支持Unicode) - Zenil
1个回答

40

如果您的Oracle数据库是使用Unicode字符集创建的,则在SQL Server中使用NVARCHAR应该迁移到Oracle中的VARCHAR2。在Oracle中,NVARCHAR数据类型存在以允许应用程序在数据库字符集不支持Unicode时使用Unicode字符集存储数据。

然而,在迁移时需要注意字符长度语义。在SQL Server中,NVARCHAR(20)分配20个字符的空间,这需要UCS-2编码最多40字节的空间。而在Oracle中,默认情况下,VARCHAR2(20)分配20个字节的存储空间。在AL32UTF8字符集中,这可能只有足够的空间来容纳6个字符,但很可能会处理更多(AL32UTF8中的单个字符需要1到3个字节)。您可能希望将Oracle类型声明为VARCHAR2(20 CHAR),这表示您希望为20个字符分配空间,而不管需要多少字节。这比试图解释为什么某些20个字符的字符串被允许,而其他10个字符的字符串被拒绝要容易得多。

您可以在会话级别更改默认长度语义,以便创建任何没有指定长度语义的表都使用字符语义而不是字节语义。

ALTER SESSION SET nls_length_semantics=CHAR;

这样,您就可以避免在定义新列时每次键入CHAR。也可以在系统级别设置该选项,但NLS团队不建议这样做--显然,Oracle提供的并非所有脚本都已经经过彻底测试,以针对更改了NLS_LENGTH_SEMANTICS的数据库。可能很少有第三方脚本这样做了。


很棒的回答……我有几个问题。在实际进行迁移时,我们是否应该担心数据截断问题?假设我们将所有 Oracle 列创建为 VARCHAR2。那么来自 SQL Server VARCHAR 列的任何数据都应该可以正确迁移。那么 SQL Server NVARCHAR 列的数据呢?SQL Server NVARCHAR 将数据存储在 UTF-16 中,而 Oracle VARCHAR2 是 UTF-8。迁移工具应该如何处理这个问题?请在主要回答中添加您的想法。 - Zenil
1
@Zenil - 我相信我已经在我的回答中涵盖了这个问题。假设您在定义Oracle列时使用字符长度语义,您的Oracle varchar2(20 char)和SQL Server nvarchar(20)将各自有20个字符的空间。如果它们各自有20个字符的空间,您就不需要担心截断问题。 - Justin Cave
我认为你解决了截断问题,但没有解决编码问题。SQL Server的NVARCHAR列是以UTF-16编码的,而Oracle的VARCHAR2列将以UTF-8编码。因此,我猜迁移工具应该意识到这一点并进行适当的转换。我们到达那个阶段时,我应该会弄清楚这一点。 - Zenil
3
内部编码并不影响实际情况。Unicode标准有不同的版本,随着时间推移,定义的字符数量也会增加,如果你从支持Unicode 6.2的数据库转移到支持此标准早期版本的数据库,可能会出现一些字符不存在的问题,但不管数据是以UTF-8、UTF-16、UTF-32还是USC-2格式存储,这些问题都会发生。然而,这通常并不是一个实际的问题。 - Justin Cave
4
在SQL Server中,NVARCHAR(20)为20个字符分配空间是不正确的描述。数字20并不代表字符数,而代表着“以字节对形式表示的字符串大小”。这一点很容易混淆,很多人都会犯这个错误,因为如果使用的字符在代码点范围0-65535之间,则每个字符的大小为2个字节,而且字符数等于数字大小。但是,如果使用的字符在代码点范围65536-1114111之间,则每个字符的大小为4个字节,并且使用NVARCHAR(20)仅为10个字符分配空间。 - Ronen Ariely

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