【问题标题】:Character string buffer too small error in Oracle Stored ProcedureOracle存储过程中的字符串缓冲区太小错误
【发布时间】:2013-07-10 01:19:10
【问题描述】:

我在 Oracle 11g 存储过程中遇到错误。错误是...

ORA-06502: PL/SQL: numeric or value error: character string buffer too small

它发生在第 31 行,包含out_cnt_tot := 0; 的行我真的不确定为什么该行有任何问题。另一个程序员创建了这个过程,我真的不熟悉 SQL 过程。谁能帮我解决这个问题?

create or replace 
PROCEDURE                  "FIP_BANKREC_PREP" 
                   (
    in_file_date in varchar2,
    in_bank_code in varchar2,
    out_cnt_apx_miss_no out integer,
    out_cnt_prx_miss_no out integer,
    out_cnt_apx_no_mtch out integer,
    out_cnt_prx_no_mtch out integer,
    out_cnt_ap_dup out integer,
    out_cnt_pr_dup out integer,
    out_cnt_bad out integer,
    out_cnt_ap_load out integer,
    out_cnt_pr_load out integer,
    out_cnt_ap_not_load out integer,
    out_cnt_pr_not_load out integer,
    out_cnt_tot out integer,
    out_message out varchar2
    ) as

file_date date;
ap_acct_no varchar2(16);
pr_acct_no varchar2(16);

-- ------------------------------------------------------
--  begin logic
-- ------------------------------------------------------
begin

  file_date := to_date(in_file_date,'yyyymmdd');
  out_cnt_tot := 0;   --- THE ERROR IS ON THIS LINE ---
  out_message := 'Test Message';

  select brec_acct_code into ap_acct_no 
    from MSSU.zwkfi_bankrec_accts
    where brec_acct_bank = in_bank_code
      and brec_acct_type = 'AP';

  select brec_acct_code into pr_acct_no 
    from MSSU.zwkfi_bankrec_accts
    where brec_acct_bank = in_bank_code
      and brec_acct_type = 'PR';      

// The rest of the procedure...

【问题讨论】:

  • 你怎么知道是第 31 行?你确定吗?您是否尝试使用十六进制编辑器查看文件?也许您可以发现一些在您的编辑器中不可见但会导致问题的 UTF-8 字符。
  • 它看起来更有可能是在那之后的那一行;这些消息中的行号有时并不完全符合您的预期。这意味着它可能是您作为out_message 传递给过程的变量的大小太小,而不是过程本身的错误。您能说明您是如何调用它的,以及如何为该调用声明变量吗?
  • 唯一传入 out_message 的是“测试消息”字面量。我们将很快添加消息,但还没有完成,所以我们只是在其中放置了一些占位符文本。对于该变量,字符串“测试消息”是否可能太短?我以前从未听说过这种情况。
  • 您将out_message 设置为'Test Message'。没关系。但是out_message 变量(错误消息中的“字符串缓冲区”)的大小由调用此过程的任何内容决定。如果它在那里定义为varchar2(10),那么分配将失败,因为该值为 12 个字符。这就是我询问来电者的原因。
  • 这是有道理的。 ASP.NET 应用程序中的某些 C# 代码正在调用此过程。 out_str_message OracleParameter 对象没有在我的代码中声明的大小。就是这样:OracleParameter prm15 = new OracleParameter("out_str_message", OracleDbType.Varchar2);prm15.Direction = ParameterDirection.Output;cmdLoad.Parameters.Add(prm15);

标签: sql oracle stored-procedures


【解决方案1】:

cmets中提到的场景的简单demo:

create or replace procedure p42(out_message out varchar2) as
begin
  out_message := 'Test message';
end p42;
/

如果我用声明的足够大的变量来调用它,那很好。我有一个 12 字符的变量,所以分配一个 12 字符的值不是问题:

declare
  msg varchar2(12);
begin
  p42(msg);
end;
/

anonymous block completed

但是,如果我犯了一个错误并使调用者的变量太小,我会收到您所看到的错误:

declare
  msg varchar2(10);
begin
  p42(msg);
end;
/

Error report:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "STACKOVERFLOW.P42", line 3
ORA-06512: at line 4
06502. 00000 -  "PL/SQL: numeric or value error%s"
*Cause:    
*Action:

错误堆栈显示过程中出错的行(第 3 行)和触发它的调用者中的行(第 4 行)。当然,根据你调用它的位置,你可能没有整个堆栈。

您提到将来会有各种错误消息。你需要确保任何调用它的东西都定义了足够大的变量来处理你的任何消息。如果它们存储在表中,您可以半自动化,否则将是手动代码审查检查。


好的,发布后看到您的 c# 评论。看起来你在打电话给this constructor;这并没有说明它得到的默认大小,但认为它可能是 1 并不是没有道理的。所以你需要调用 this constructor 来明确指定大小:

OracleParameter(String, OracleType, Int32)
初始化使用参数名称的 OracleParameter 类的新实例, 数据类型和长度。

...类似于:

OracleParameter prm15 = new OracleParameter("out_str_message",
    OracleDbType.Varchar2, 80);

除非有办法在创建后重置大小,我看不到。 (不是我用过的东西!)。

【讨论】:

  • 看起来像在我的 OracleParameter() 构造函数中添加 12 的长度可以解决这个问题。感谢您的帮助。
猜你喜欢
  • 2018-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-21
  • 2019-11-17
  • 2012-05-23
  • 2021-11-15
  • 2014-10-08
相关资源
最近更新 更多