ORA-22835: 缓冲区太小和 ORA-25137: 数据值超出范围
Posted
技术标签:
【中文标题】ORA-22835: 缓冲区太小和 ORA-25137: 数据值超出范围【英文标题】:ORA-22835: Buffer too small and ORA-25137: Data value out of range 【发布时间】:2022-01-02 03:29:09 【问题描述】:我们使用的软件具有有限的 Oracle 功能。我需要通过确保它具有特定值来过滤 CLOB 字段。通常,在这个软件之外我会做类似的事情:
DBMS_LOB.SUBSTR(t.new_value) = 'Y'
但是,这不受支持,因此我尝试改用 CAST
。我尝试了许多不同的尝试,但到目前为止,我发现了这些:
该软件有一个内置的查询检查器/验证器,这些是它显示为无效的:
DBMS_LOB.SUBSTR(t.new_value)
CAST(t.new_value AS VARCHAR2(10))
CAST(t.new_value AS NVARCHAR2(10))
但是,验证器确实接受这些:
CAST(t.new_value AS VARCHAR(10))
CAST(t.new_value AS NVARCHAR(10))
CAST(t.new_value AS CHAR(10))
不幸的是,即使验证器允许这些验证器通过,当运行查询以获取数据时,我在使用 VARCHAR
或 NVARCHAR
时得到 ORA-22835: Buffer too small
。我在使用CHAR
时得到ORA-25137: Data value out of range
。
在过滤数据时,是否有其他方法可以尝试检查我的 CLOB 字段是否具有特定值?如果没有,我该如何解决我当前的问题?
【问题讨论】:
new_value
有多长?将列声明为clob
然后只在其中存储一个字符似乎很奇怪。您得到的错误意味着存储的值超过 10 个字符/字节长。它们是否可能超过 32k?
@JustinCave new_value
跟踪更改为字段值,因此它是任意长度。它还跟踪可能包含大量字符的TEXT
字段的更改。但我现在需要的只是一个文本,N
或 Y
。
Oracle 没有text
数据类型。这些错误意味着您正在查看的值超过 10 个字符。根据软件正在执行的操作,您的cast
可能会在您拥有的任何其他谓词之前应用,这些谓词将您感兴趣的行减少到仅具有单个数据字符的行。我不知道该软件是否让您能够控制它,但如果它甚至不允许您使用内置软件包,我会倾向于怀疑它。是否允许instr
或substr
?
@JustinCave 抱歉,是的,Oracle 没有 TEXT
- 我一直在混合使用 Oracle 和 mysql。此外,查询验证器无法识别 SUBSTR
和 INSTR
。
@JustinCave 你所说的CAST
被应用之前 将行减少到我只感兴趣的内容似乎是这里的问题。我必须创建一个子查询来过滤行并且只获取我知道只包含一个字符的行。然后我做了CAST
after。如果你把它作为答案,我会接受它。谢谢!
【参考方案1】:
使用这个作为样本数据
create table tab1(col clob);
insert into tab1(col) values (rpad('x',3000,'y'));
您需要使用dbms_lob.substr(col,1)
来获取第一个 字符(来自默认的offset
= 1)
select dbms_lob.substr(col,1) from tab1;
DBMS_LOB.SUBSTR(COL,1)
----------------------
x
请注意,子字符串的 default amount
(= 长度)是 32767
,因此仅使用 DBMS_LOB.SUBSTR(COL)
会返回比您预期的更多。
CAST
for CLOB
确实 not cut 将字符串转换为强制转换的长度,但是(如您所见)如果原始字符串返回异常 ORA-25137: Data value out of range
比铸造长度更长。
正如CAST
声明所记录的那样
CAST 不直接支持任何 LOB 数据类型。当您使用 CAST 将 CLOB 值转换为字符数据类型或将 BLOB 值转换为 RAW 数据类型时,数据库会隐式地将 LOB 值转换为字符或原始数据,然后将结果值显式转换为目标数据类型。 如果结果值大于目标类型,则数据库返回错误。
【讨论】:
不幸的是,即使添加了偏移量,查询验证器也无法识别DBMS_LOB.SUBSTR()
,所以我不能使用它。我认为CAST
能够切断字符串,因为我们还必须使用TRUNC
的解决方法:CAST(CAST(date_field AS VARCHAR(9)) AS DATE)
并且它有效。它摆脱了时间部分。我希望我们可以为这个做类似的事情。
是的,这适用于VARCHAR
,但不幸的是不适用于CLOB
,我更新了答案。 @PatrickGregorio【参考方案2】:
您收到的错误表明 Oracle 正在尝试将 CAST(t.new_value AS VARCHAR(10))
应用于 new_value
超过 10 个字符的行。考虑到您的描述,这是有道理的,new_value
是一个通用审计字段,其值来自具有各种数据长度的大量不同表。鉴于此,您需要以一种强制优化器将您应用 cast
的行集减少到仅在应用 @ 之前 new_value
只有一个字符的行的方式来构造查询987654326@.
不知道您使用的软件为构建代码提供了什么样的范围,我不确定您有哪些选择。请注意,根据您需要的稳健程度,优化器具有相当大的灵活性,可以选择以任意顺序在投影上应用谓词和函数。因此,即使您找到了一种可行的方法,将来当统计信息发生变化或数据库升级并且 Oracle 决定选择不同的计划时,它也可能停止工作。
【讨论】:
以上是关于ORA-22835: 缓冲区太小和 ORA-25137: 数据值超出范围的主要内容,如果未能解决你的问题,请参考以下文章
ORA-22835 缓冲区对于 CLOB 到 CHAR 转换或 BLOB 到 RAW 转换而言太小