支持超过4000字节的varchar2类型

Oracle中最常用的字符串类型可能就是varchar2了,但是一直以来,让人吐槽最多的,可能就是他的存储容量,12c之前,允许存储4000字节,请注意这的单位是字节,如果你按照非常规的字符定义字段,就得结合字符集,确定他能存储的容量。如果要存储超过这个限制的字符,就得改为CLOB类型了,他的容量是4G,另外一种变通的形式,不想使用大字段,就将要存储的字符拆成多个varchar2类型的字段,读的时候拼接这些字段,起到一样的效果。

从12c开始,varchar2(实际包括nvarchar2和raw)开始支持32767个字节,即32K的容量。他是由max_string_size这个参数控制的,默认值是STANDARD,为了支持32K,需要将其改为EXTENDED,

SQL> show parameter max_string_size
NAME             TYPE   VALUE
---------------- ------ ----------
max_string_size  string STANDARD

从官方文档,我们知道,non-CDB、CDB、PDB都支持这个参数,

(1) 如果是non-CDB,步骤较为简单,

1. 关闭数据库,shutdown immediate。

2. 启动数据库到升级模式,startup upgrade。

3. 修改max_string_size=’EXTENDED’,scope=both。
4. 执行@?/rdbms/admin/utl32k.sql
5 .重启数据库至正常open状态,shutdown immdeiate -> startup。

(2) 如果是PDB,步骤和上述相同,只是必须在PDB执行以下操作,

SQL> alter pluggable database bisalpdb2 close;
Pluggable database altered.


SQL> alter pluggable database bisalpdb2 open upgrade;
Pluggable database altered.


SQL> alter system set max_string_size=extended scope=both;
System altered.


SQL> @?/rdbms/admin/utl32k.sql
Session altered.
//脚本执行速度,应该和当前数据库中的对象数量有关。


SQL> alter pluggable database bisalpdb2 close;
Pluggable database altered.


SQL> alter pluggable database bisalpdb2 open;
Pluggable database altered.

此时的参数值,已经改为EXTENDED,

SQL> show parameter max_string_size
NAME             TYPE   VALUE
---------------- ------ --------
max_string_size  string EXTENDED

我们就可以创建一个32767字节的varchar2类型字段,

SQL> create table test(c varchar2(32767));
Table created.

(3) 如果是CDB,执行以上操作,还需要单独设置pdb$seed以及其他pdb的max_string_size,操作过程:

close->open upgrade->max_string_size->close->open

这就不操作了。

虽然能支持32K的字符串了,但是还存在一些风险和限制,例如,

(1) EXTENDED只支持heap table,不支持cluster table簇表和index-organized tables索引组织表。

(2) max_string_size如果改为EXTENDED,不能再改为STANDARD,这是单向操作,因此要提前设计,

SQL> alter pluggable database bisalpdb2 close;
Pluggable database altered.


SQL> alter pluggable database bisalpdb2 open upgrade;
Pluggable database altered.


SQL> alter system set max_string_size=standard scope=both;
alter system set max_string_size=standard scope=both
*
ERROR at line 1:
ORA-02097: parameter cannot be modified because specified value is invalid
ORA-14693: The MAX_STRING_SIZE parameter must be EXTENDED.

(3) 32K的字符串在Oracle内部还是以LOB的方式存储的,容易造成行链接,对数据读取的性能产生一定的影响。

(4) 索引中的字段,不能直接支持EXTENDED,需要删除索引,更改字段,再重建索引。

(5) 官方文档上提到了如下这些场景,第一个场景,应该和索引长度限制相关,如果按照标准8k的数据块,一个B树索引块所支持的索引长度可能就6千多字节,这就和在MySQL中索引键值长度的问题很像了(《小白学习MySQL - 索引键长度限制的问题》),或者通过substr截取创建索引,或者通过substr创建虚拟列,再创建索引,

Altering MAX_STRING_SIZE will update database objects and possibly invalidate them, as follows:

Tables with virtual columns will be updated with new data type metadata for virtual columns of VARCHAR2(4000), 4000-byte NVARCHAR2, or RAW(2000) type.

Functional indexes will become unusable if a change to their associated virtual columns causes the index key to exceed index key length limits. Attempts to rebuild such indexes will fail with ORA-01450: maximum key length exceeded.


Views will be invalidated if they contain VARCHAR2(4000), 4000-byte NVARCHAR2, or RAW(2000) typed expression columns.


Materialized views will be updated with new metadata VARCHAR2(4000), 4000-byte NVARCHAR2, and RAW(2000) typed expression columns

因此,为了能从语法上支持32K的varchar2,还是需要一些代价的,究竟是设置max_string_size,还是选择CLOB,或者是拆分字段,可能就得结合实际的场景,综合考量。

近期更新的文章:

“自以为对的”MyBatis空闲连接探测的机制

积累一些SQL

创建主键的三种方式对指定索引表空间操作的纠正

Oracle优化器的“短路”

MySQL行转列的小需求

Oracle的greatest和least函数

我的股市生涯

Oracle创建主键的三种方式

非Oracle Linux下Oracle 19c CDB数据库安装

案例纠正一则

Redis和Sentinel的安装部署和配置

“火线”和“零线”

通过索引提升SQL性能案例一则

如何手动添加jar包到maven本地库?

1元股权转让的一点思考

如何打造一个经常宕机的业务系统?

Linux恢复误删文件的操作

Linux的scp指令使用场景

Oracle处理IN的几种方式

如何搭建一支拖垮公司的技术团队?

IP地址解析的规则

MySQL的skip-grant-tables

国产数据库不平凡的一年

Oracle要求顺序的top数据检索问题

日常工作中碰到的几个技术问题

了解一下sqlhc

Oracle的MD5函数介绍

Oracle 19c的examples静默安装

sqlplus登录缓慢的解决

VMWare 11安装RedHat Linux 7过程中碰到的坑

COST值相同?是真是假?

Oracle 11g的examples静默安装

文章分类和索引:

公众号700篇文章分类和索引

<think>好的,我现在需要介绍一下VARCHAR2这个数据库中的数据类型。首先,我要确保自己理解正确,然后按照用户的要求用中文清晰解释。 首先,VARCHAR2Oracle数据库里的一个数据类型,用来存储可变长度的字符串。可变长度意味着它会根据实际存储的数据调整所占用的空间,比如存"abc"就比存"abcdef"用的空间少。这一点和CHAR类型不同,CHAR是固定长度的,就算存的数据短,也会用空格填充到指定长度。 接下来要讲清楚最大长度的问题。在Oracle 11g及之前的版本,VARCHAR2的最大长度是4000字节,而12c之后支持32767字节,但需要开启扩展VARCHAR2功能。不过实际应用中可能还是受限于数据库块大小或者其他限制,需要注意。 然后要提到字符集的影响。VARCHAR2的长度可以按字节或字符来定义,比如VARCHAR2(10 BYTE)和VARCHAR2(10 CHAR)的区别。如果数据库使用多字节字符集(比如UTF-8),按字节计算的话,实际能存储的字符数可能更少。这点对用户来说很重要,特别是处理多语言数据时。 存储机制方面,VARCHAR2只占用实际数据长度加上长度标识符的空间,通常是1到3个字节。比如存"Hello"需要5个字节的数据加上1个字节记录长度,总共6个字节。而CHAR类型则会固定占用定义的长度,比如CHAR(10)存"Hello"会占用10个字节,后面用空格填充。 性能方面,VARCHAR2存储空间上更高效,适合存储长度变化大的数据。但频繁更新导致长度变化可能会引起行迁移,影响性能。CHAR类型在查询时可能稍微快一点,因为长度固定,适合长度基本不变的数据,比如国家代码。 使用场景需要分情况说明:VARCHAR2适合用户名、地址、描述等长度不固定的数据;CHAR适合像性别代码、状态码等长度固定的数据。 注意事项部分,要提到OracleVARCHARVARCHAR2的区别,虽然现在VARCHARVARCHAR2是同义词,但推荐用VARCHAR2,因为未来可能有变化。还有索引和比较时的空格处理,CHAR类型会自动补空格,而VARCHAR2不会,这可能会影响查询结果。 最后用例子说明,比如创建表的时候如何定义VARCHAR2字段,插入数据时的表现,以及和CHAR的对比。这可以帮助用户更直观地理解。 检查一下是否遵循了系统级指令:行内公式用$...$,独立公式单独成段用$$...$$。不过这里可能不需要数学公式,但如果有提到长度计算的话可能需要,比如存储空间的计算。例如,VARCHAR2的实际存储空间是数据长度加上1到3字节的长度标识符,可以写成$L + 1$到$L + 3$,其中$L$是数据长度。不过用户的问题是关于VARCHAR2的,可能不太需要数学表达式,但如果有相关内容的话要按格式处理。 还要确保用中文回答,结构清晰,分点说明,帮助用户逐步理解。可能需要分节,比如定义、特点、使用场景、注意事项等,用标题或者编号列出。避免使用Markdown格式,所以用数字或项目符号的话可能需要用文字表示。 总结一下,内容需要涵盖定义、长度限制、字符集影响、存储机制、性能比较、使用场景、注意事项和示例。这样用户能全面了解VARCHAR2,并知道何时使用它以及需要注意的问题。</think>VARCHAR2Oracle 数据库中用于存储**可变长度字符串**的数据类型。以下是逐步解析: --- ### 1. **定义与核心特性** - **可变长度**:仅占用实际数据长度 + 小额外开销(长度标识符),例如存储 `"ABC"` 仅需 3 字符空间,而非固定长度。 - **字符集敏感**:长度可定义为字节(`BYTE`)或字符(`CHAR`)。 例如: - `VARCHAR2(10 BYTE)`:允许最多 10 字节(UTF-8 中可能少于 10 个汉字)。 - `VARCHAR2(10 CHAR)`:允许最多 10 个字符(无论字节数)。 --- ### 2. **长度限制** - **Oracle 11g 及之前**:最大 `4000 字节`。 - **Oracle 12c+**:支持扩展至 `32767 字节`,但需启用 `MAX_STRING_SIZE=EXTENDED` 参数。 - **实际限制**:可能受数据库块大小或字段定义约束(如单行总长度不超过块大小的 1/2)。 --- ### 3. **存储机制** - **数据存储**:实际字符串 + 1-3 字节的长度标识符。 - 例:字符串 `"Hello"` 存储为 `长度标识符(1字节) + 5字节数据`,共 $5+1=6$ 字节。 - **对比 CHAR**:CHAR 固定占用定义长度,例如 `CHAR(10)` 存储 `"Hi"` 会填充 8 空格。 --- ### 4. **性能与适用场景** - **优势场景**: - 存储长度变化大的数据(如用户输入、地址)。 - 节省存储空间,减少 I/O 开销。 - **劣势场景**: - 频繁更新导致长度变化时,可能引发行迁移(Row Migration)。 - 短字符串查询略慢于 CHAR(因变长需解析)。 --- ### 5. **与 CHAR/VARCHAR 的区别** | 类型 | 是否填充空格 | 推荐使用场景 | Oracle 中备注 | |-----------|--------------|----------------------|-----------------------------| | **CHAR** | 是 | 固定长度(如国家码) | 定长字段 | | **VARCHAR2** | 否 | 变长数据(如描述) | Oracle 推荐替代 VARCHAR | | **VARCHAR** | 否 | 同 VARCHAR2 | Oracle 中为 VARCHAR2 同义词 | --- ### 6. **注意事项** - **索引与比较**:VARCHAR2 比较时**区分空格**,例如 `'A'` 和 `'A '` 视为不同。 - **迁移兼容性**:其他数据库(如 MySQL)的 `VARCHAR` 行为可能与 Oracle 的 `VARCHAR2` 不同。 - **设计建议**:优先用 `VARCHAR2` 除非明确需要固定长度。 --- ### 7. **示例代码** ```sql -- 创建表 CREATE TABLE users ( id NUMBER, username VARCHAR2(50 CHAR), -- 按字符定义 email VARCHAR2(100 BYTE) -- 按字节定义 ); -- 插入数据 INSERT INTO users VALUES (1, '张三', 'zhangsan@example.com'); -- 查询对比 CHAR 和 VARCHAR2 SELECT 'Hello' AS char_col FROM dual WHERE CAST('A' AS CHAR(2)) = 'A '; -- 返回 1 行(空格被忽略) SELECT 'Hello' AS varchar2_col FROM dual WHERE CAST('A' AS VARCHAR2(2)) = 'A '; -- 无结果(严格匹配) ``` --- 通过理解以上特性,可合理选择 VARCHAR2 优化存储与查询效率。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值