Oracle 和 SQL Server 中的 NVARCHAR 之间的区别?

Posted

技术标签:

【中文标题】Oracle 和 SQL Server 中的 NVARCHAR 之间的区别?【英文标题】:Difference between NVARCHAR in Oracle and SQL Server? 【发布时间】:2013-08-21 21:53:04 【问题描述】:

我们正在将一些数据从 sql server 迁移到 oracle。对于在 SQL Server 中定义为 NVARCHAR 的列,我们开始在 Oracle 中创建 NVARCHAR 列,认为它们相似..但看起来它们不是。

我已经阅读了几篇关于 *** 的帖子,想确认一下我的发现。

如果数据库字符集是 AL32UTF8(在我们的例子中是这样),Oracle VARCHAR2 已经支持 unicode。

SQLServer VARCHAR 支持 unicode。 SQLServer 明确要求列为 NCHAR/NVARCHAR 类型,以便以 unicode 存储数据(特别是 2 字节 UCS-2 格式)..

因此说 SQL Server NVARCHAR 列可以/应该迁移为 Oracle VARCHAR2 列是否正确?

【问题讨论】:

微软确认 Oracle NVARCHAR2 SQLServer NVARCHAR..但我想确认的是 Oracle VARCHAR2 SQLServer NVARCHAR ? (因为 oracle VARCHAR2 已准备好 unicode) 【参考方案1】:

是的,如果您的 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 类型声明为@ 987654328@ 表示您想为 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 - 我相信我已经在回答中提到了这一点。假设您在 Oracle 中定义列时使用字符长度语义,您的 Oracle varchar2(20 char) 和 SQL Server nvarchar(20) 将各有 20 个字符的空间。如果它们每个都有 20 个字符的空间,则不必担心截断问题。 我认为您解决了截断问题,但没有解决编码问题。 SQL server NVARCHAR 列以 UTF-16 编码,而 oracle VARCHAR2 列将以 UTF-8 编码 ..所以我猜迁移工具应该意识到这一事实并进行适当的转换。当我们达到那个阶段时,我应该会发现这一点.. @Zenil - 内部编码不起作用。好吧,Unicode 标准的不同修订版随着时间的推移扩展了定义的字符数量,因此,如果您碰巧从支持 Unicode 6.2 的数据库(其中定义了某些字符)到支持该早期版本的数据库在该字符不存在的标准中,您会遇到问题,但无论数据是以 UTF-8 还是 UTF-16 或 UTF-32 还是 USC-2 存储的,都会发生这些问题。不过,这通常不是一个实际问题。 "In SQL Server, a NVARCHAR(20) allocates space for 20 characters" : @JustinCave ,这是不正确的。数字 20 不代表字符数,而是“字节对中的字符串大小”。这很令人困惑,很多人都会犯这个错误,因为如果您使用代码点 0-65535 范围内的字符,那么每个字符大小是 2 个字节,并且数字等于字符数。 但是如果您使用 65536-1114111 范围内的字符,则每个字符大小为 4 个字节,使用 NVARCHAR(20) 只能为 10 个字符分配空间。

以上是关于Oracle 和 SQL Server 中的 NVARCHAR 之间的区别?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 中的 Oracle 样式联接

为啥此相关子查询在 Oracle 和 SQL Server 中的工作方式不同

sql server和oracle中查询结果返回指定行数的语句

只允许通过 sql server、oracle 和 postgres 中的 jdbc 更新表

SQL Server和Oracle数据库索引介绍

从 SQL Server 转换 Oracle 中的更新 SQL