Oracle NCHAR与NVARCHAR2 最大字符数和最大字节数

article/2025/10/1 0:06:11

根据官方文档和实验测试整理一下常见问题以及相关结论,以NVARCHAR2为主。

 

一、 含义及用途

NCHAR和NVARCHAR2都是Unicode数据类型,存储Unicode字符数据。NCHAR和NVARCHAR2数据类型的对应的国家字符集(NLS_NCHAR_CHARACTERSET)只能是AL16UTF16或者UTF8。

  • NCHAR字段存储对应于国家字符集固定长度的字符串。
  • NVARCHAR2则存储可变长度字符串

NCHAR和NVARCHAR2均有最大字符长度和最大字节数的限制,这两个要求必须同时满足。下面分别来看

 

二、 最大字符长度

我们知道,对于char和varchar类型,是由nls_length_semantics参数的值来决定varchar(100)中的100指的字节数还是字符数(参考 聊聊字符串数据长度和nls_length_semantics参数),但对于NCHAR和NVARCHAR2来说,无论nls_length_semantics的值是什么,都相当于是char。因此NVARCHAR2(100)中的100一定是字符数。

When you create a table with an NCHAR or NVARCHAR2 column, the maximum size specified is always in character length semantics. Character length semantics is the default and only length semantics for NCHAR or NVARCHAR2.

最大字符长度可以定义为多少呢?

12c之前,取决于国家字符集设置

  • AL16UTF16:2000
  • UTF8:4000

从12.1开始,取决于两个设置 —— MAX_STRING_SIZE和国家字符集

  • 16383 if MAX_STRING_SIZE = EXTENDED and the national character set is AL16UTF16

  • 32767 if MAX_STRING_SIZE = EXTENDED and the national character set is UTF8

  • 2000 if MAX_STRING_SIZE = STANDARD and the national character set is AL16UTF16

  • 4000 if MAX_STRING_SIZE = STANDARD and the national character set is UTF8

根据这个定义,例如我们设置MAX_STRING_SIZE = STANDARD,NLS_NCHAR_CHARACTERSET=AL16UTF16,那最多就只能定义为NVARCHAR2(2000),即最多能存2000个字符;如果NLS_NCHAR_CHARACTERSET=UTF8,那最多能定义为NVARCHAR2(4000),即最多能存4000个字符。

 

三、 最大可储存字节数

对于NCHAR(无论版本),最大长度为2000字节,这个值是固定死的,不受其他参数影响。

对于NVARCHAR2,12c之前,最大长度为4000字节,这个值也是固定死的。

12.1开始,NVARCHAR2还受MAX_STRING_SIZE 参数影响,如果MAX_STRING_SIZE = STANDARD则与之前版本相同,最大长度为4000字节;如果MAX_STRING_SIZE = EXTENDED,最大长度为32767字节

即使按照前面的定义NLS_NCHAR_CHARACTERSET=UTF8,NVARCHAR2(4000)最多应该能存4000个字符,如果实际的数据大小超过了4000字节,就会遇到报错。由于UTF8中一个英文占1 byte,一个中文占3 byte,此时NVARCHAR2(4000)最多只能存1333个中文(即3999 byte)。

如果是用的NLS_NCHAR_CHARACTERSET=AL16UTF16,由于AL16UTF16无论中文英文每个都是占2 byte,此时NVARCHAR2(2000) 最多只能存2000个中/英文(即4000 byte)。

 

四、 客户端国家字符集NLS_NCHAR

如果你是用的NLS_NCHAR_CHARACTERSET=AL16UTF16,用客户端实际insert中文时应该会发现最多就只能插入1333个中文,再多就报错了,纯英文则没有这个限制,并且插入之后使用lengthb查看字节数,只是2666。很奇怪,中文字符数据并不符合第三节对AL16UTF16的规定,反而符合对UTF8的规定。

经过一番搜索,在文档 Selecting LENGTHB of an NVARCHAR2 does not return the byte length (文档 ID 2390023.1) 中找到了答案。

这个问题跟客户端国家字符集NLS_NCHAR的设置有关,NLS_NCHAR默认是UTF8,所以我们在客户端输入一个中文,实际上是占的3个byte。而输入1333个字符时,实际上已经占了3999 byte,所以再加中文就报错了。如果想要能输入2000个中文,应该要设置NLS_NCHAR环境变量为AL16UTF16(但测试的时候发现改了也没用,还没研究出来为啥)。

为什么把1333个中文成功插入表后用lengthb查又变成了2666,应该是在插入时Oracle进行了字符集转换,把客户端的UTF8国家字符集转成了AL16UTF16,因此每个字符长度又变成了2 byte。

如果使用concat函数拼接我们前面输入的1000个中文变成2000个中文,会发现实际上是可以成功的,因为此时每个字符长度为2 byte,NVARCHAR2(2000)最多可以放2000个字符,最多刚好占4000 byte。

select length(v_byte),lengthb(v_byte) from t_byte;
insert into t_byte select concat(v_byte,v_byte) from t_byte where length(v_byte)=1000;

 

参考

https://docs.oracle.com/database/121/SQLRF/sql_elements001.htm#SQLRF30020

https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT1825

http://www.databases-la.com/?q=node/55

https://blog.darkthread.net/blog/nvarchar2-max-len-for-chinese/

https://oracle-base.com/articles/12c/extended-data-types-12cR1

https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/datatype-limits.html#GUID-963C79C9-9303-49FE-8F2D-C8AAF04D3095

Selecting LENGTHB of an NVARCHAR2 does not return the byte length (文档 ID 2390023.1)


http://chatgpt.dhexx.cn/article/f2hLINDV.shtml

相关文章

foreach 中如何给数组赋值

最近发现,在foreach中给数组赋值,在foreach外,数组是没有变化的,对此情况,有特定的处理方法,特此记录一下: 如下,就是在foreach中,加上 $res[$k] $v;给$res重新赋值&am…

数组与数组赋值

int类型数组赋值 #include<stdio.h> int main() { int a[] {1,2,3,4,5,7}; printf("a[3]%d", a[3]); return 0; } char类型数组赋值 1.直接字符串赋值 char a[] "q,0/d"; 2.逐个赋值 char b[] { d,b,3,&am…

VBA 不能给数组赋值,其实只是不能给静态数组整体赋值

1 问题&#xff1a;VBA报错&#xff1a;不能给数组赋值&#xff01; 其实并不是 所有数组不能赋值其实是不能给静态数组&#xff0c;整体赋值&#xff01;只是因为当前处理的是一个静态数组 2 什么是静态数组 &#xff08;只是大小静态&#xff01;&#xff01; 赋值可变&…

天呐!java从键盘给数组赋值

开头 该文档在Github上收获5K+star的Java核心神技(这参数,质量多高就不用我多说了吧)非常全面,包含基础知识、Java集合、JVM、多线程并发、spring原理、微服务、Netty 与RPC 、Kafka、日记、设计模式、Java算法、数据库、Zookeeper、分布式缓存、数据结构等等内容非常丰富…

php数组赋值方式,php数组赋值方式

推荐操作系统&#xff1a;windows7系统、PHP5.6、DELL G3电脑 1、两种赋值 (1)传值赋值 在PHP中&#xff0c;传递赋值是默认的传递方式。如果某个变量的值被赋予了另一个变量&#xff0c;那么改变其中一个的值对其他变量没有影响。 (2)引用赋值 引用赋值意味着新变量简单地引用…

在java中给数组赋值,java中给数组赋值的方法

1、数组操作中&#xff0c;可以使用等于()赋值 注意&#xff1a;此时新数组只是指向原数组的存储空间&#xff0c;并没有重新申请新的空间。 实例&#xff1a;public class ArrayTest{ public static void main(String args[]){ // 1 int[] anew int[4]; a[0]1; a[1]2; a[2]3; …

SSDP 服务发现协议

https://blog.csdn.net/braddoris/article/details/41479171 SSDP在Android上的实现 https://blog.csdn.net/iblade/article/details/81948805

【SSDP 协议介绍】

SSDP&#xff0c;即简单服务发现协议&#xff08;SSDP&#xff0c;Simple Service Discovery Protocol&#xff09;&#xff0c;是一种应用层协议&#xff0c;是构成通用即插即用(UPnP)技术的核心协议之一。 实现 简单服务发现协议是在HTTPU和HTTPMU的基础上实现的协议。 按照协…

RSTP和MSTP协议的原理

一.RSTP 1.RSTP&#xff08;Rapid Spanning Tree Protocol&#xff0c;快速生成树协议&#xff09;是STP协议的优化版&#xff0c;协议为802.1w。 2.RSTP具备STP的所有功能 3.RSTP可以实现快速收敛 在某些情况下&#xff0c;端口进入转发状态的延时大大缩短&#xff0c;从而…

简单服务发现协议SSDP【转】

来自&#xff1a;https://blog.csdn.net/wuruixn/article/details/23843877 SSDP:Simple Sever Discovery Protocol,简单服务发现协议是一种应用层协议&#xff08;常用于寻找upnp设备&#xff09;&#xff0c;此协议为网络客户提供一种无需任何配置、管理和维护网络设备服务的…

SIP协议-05 SDP协议

文章目录 1 SDP简介2 SDP协议格式2.1 字段描述2.1.1 Version&#xff08;必选&#xff09;2.1.2 origion&#xff08;必选&#xff09;2.1.3 Session Name&#xff08;必选&#xff09;2.1.4 Connection Data&#xff08;可选&#xff09;2.1.5 Bandwidth&#xff08;可选&…

SDP协议总结

一、基本要求 1、SDP的表示 SDP(Session Description Portocol)会话描述协议&#xff0c;通常通过内容类型为"application/sdp"的MIME来表示。 2、媒体和传送信息 SDP可包括以下媒体信息&#xff1a; 媒体类型&#xff08;音频、视频等&#xff09;&#xff1b;…

简单服务发现协议SSDP

SSDP:Simple Sever Discovery Protocol,简单服务发现协议是一种应用层协议&#xff08;常用于寻找upnp设备&#xff09;&#xff0c;此协议为网络客户提供一种无需任何配置、管理和维护网络设备服务的机制。此协议采用基于通知和发现路由的多播发现方式实现。协议客户端在保留的…

协议--SIP/SDP

参考资料 会话初始协议SIP与SDP简介完整SIP/SDP媒体协商概论-SIP/WebRTC概要 1. 什么是SIP 1.1 关于SIP通话的一个形象比喻 生活中&#xff0c;我们想要找一个人互相聊天&#xff0c;首先你到找到这个人、你的声音得传递到对方&#xff0c;对方能听到你的声音&#xff0c; …

SSDP 简单服务发现协议 .

http://blog.csdn.net/lilypp/article/details/6631951 cache network 网络 algorithm ext service SSDP 简单服务发现协议&#xff0c;是应用层协议&#xff0c;是构成UPnP&#xff08;通用即插即用&#xff09;技术的核心协议之一。它为网络客户端&#xff08;network client…

SSDP Protocol

SSDP 简单服务发现协议&#xff0c;是应用层协议&#xff0c;是构成UPnP&#xff08;通用即插即用&#xff09;技术的核心协议之一。它为网络客户端&#xff08;network client&#xff09;提供了一种发现网络服务&#xff08;network services&#xff09;的机制&#xff0c;采…

SDP协议详细介绍

SDP 协议分析 http://www.cnblogs.com/qingquan/archive/2011/08/02/2125585.html 一、SDP协议介绍 SDP 完全是一种会话描述格式 ― 它不属于传输协议 ― 它只使用不同的适当的传输协议&#xff0c;包括会话通知协议&#xff08;SAP&#xff09;、会话初始协议&#xff08;SIP…

SSDP 简单服务发现协议

SSDP 简单服务发现协议,是应用层协议,是构成UPnP(通用即插即用)技术的核心协议之一。它为网络客户端(network client)提供了一种发现网络服务(network services)的机制,采用基于通知和发现路由的多播方式实现。 SSDP多播地址:239.255.255.250:1900(IPv4),FF0x::C(…

设备发现协议SSDP实现

原理&#xff1a; 1.将socket加入239.255.255.250&#xff0c;端口 1900 2.客户端&#xff1a;通过设置setsockopt IPPROTO_IP,IP_ADD_MEMBERSHIP属性&#xff0c;可向ssdp组进行组播。 3.服务端&#xff1a;通过设置绑定239.255.255.250:1900进行数据接收&#xff0c;通过s…

wireshark-协议分析【初见】(NBNS协议,SSDP协议、IGMPv2)

写在前面 win7:192.168.2.150&#xff08;00-0c-29-CF-D3-0F&#xff09; kali:192.168.2.120&#xff08;00:0c:29:e7:1c:e5&#xff09; &#xff08;均使用的vmware虚拟机平台&#xff09; 该系列并不会太关注wireshark的用法&#xff0c;重点关注协议交换时数据包的情况。…