【问题标题】:Oracle pipelined function: ORA-06502 numeric or value errorOracle 流水线函数:ORA-06502 数值或值错误
【发布时间】:2021-03-05 18:57:39
【问题描述】:

我编写了一个流水线函数来查询远程数据库中的数据。我不断得到

ORA-06502:PL/SQL:数字或值错误:字符串缓冲区太 小。

我想我确实理解何时会发生此错误,例如,当表列定义为 VARCHAR2(10) 并且您尝试插入大于 10 字节的内容时。但在这种情况下,我真的看不出有什么问题。

也许我首先显示本地和远程数据库的参数。我认为这可能很重要,将两个 DB 上的 NLS_LENGTH_SEMANTICS 设置为 BYTE

本地数据库(存储流水线函数的地方): params local db

远程数据库(从那里查询数据): params remote db

现在本地数据库中的代码:

create or replace function f_get_pl_data return tb_pl_palette pipelined is
begin
    for i in (select p.*, 123 LAGER from palette@myremotedb p)
    loop
      pipe row(tt_pl_palette(i.pid,i.bereich,i.regal,i.fach,i.ebene,i.vol_klasse,i.lhm_typ,i.zustand,i.neu_datum,
               i.neu_zeit,i.neu_usr,i.aender_datum,i.aender_zeit,i.aender_usr,i.verl_datum,i.tournr,
               i.fil_nr,i.retournr,i.fz_nr,i.fahrer_nr,i.eroeff_auswahl,i.tpa_knz,i.lfsaender_knz,
               i.verladen_am,i.verladen_um,i.verladen_von,i.verladen_von2,i.leer_gew,i.soll_gew,
               i.ist_gew,i.lager));
    end loop;
    
    return;
end;
CREATE OR REPLACE TYPE "TT_PL_PALETTE" AS OBJECT (
  pid            VARCHAR2(14),
  bereich        VARCHAR2(2),
  regal          VARCHAR2(2),
  fach           VARCHAR2(3),
  ebene          VARCHAR2(2),
  vol_klasse     INTEGER,
  lhm_typ        INTEGER,
  zustand        INTEGER,
  neu_datum      DATE,
  neu_zeit       VARCHAR2(11),
  neu_usr        VARCHAR2(4),
  aender_datum   DATE,
  aender_zeit    VARCHAR2(11),
  aender_usr     VARCHAR2(4),
  verl_datum     DATE,
  tournr         VARCHAR2(6),
  fil_nr         VARCHAR2(4),
  retournr       VARCHAR2(10),
  fz_nr          INTEGER,
  fahrer_nr      INTEGER,
  eroeff_auswahl INTEGER,
  tpa_knz        VARCHAR2(1),
  lfsaender_knz  VARCHAR2(1),
  verladen_am    DATE,
  verladen_um    VARCHAR2(11),
  verladen_von   VARCHAR2(4),
  verladen_von2  VARCHAR2(4),
  leer_gew       NUMBER(7,3),
  soll_gew       NUMBER(7,3),
  ist_gew        NUMBER(7,3),
  lager          NUMBER
  )
CREATE OR REPLACE TYPE "TB_PL_PALETTE"  as TABLE OF TT_PL_PALETTE

这是远程数据库上的表规范:

create table PALETTE
(
  pid            VARCHAR2(14) not null,
  bereich        VARCHAR2(2) not null,
  regal          VARCHAR2(2) not null,
  fach           VARCHAR2(3) not null,
  ebene          VARCHAR2(2) not null,
  vol_klasse     INTEGER,
  lhm_typ        INTEGER,
  zustand        INTEGER,
  neu_datum      DATE default trunc(sysdate),
  neu_zeit       VARCHAR2(11) default to_char(sysdate, 'HH24:MI:SS'),
  neu_usr        VARCHAR2(4),
  aender_datum   DATE,
  aender_zeit    VARCHAR2(11),
  aender_usr     VARCHAR2(4),
  verl_datum     DATE,
  tournr         VARCHAR2(6),
  fil_nr         VARCHAR2(4),
  retournr       VARCHAR2(10),
  fz_nr          INTEGER,
  fahrer_nr      INTEGER,
  eroeff_auswahl INTEGER,
  tpa_knz        VARCHAR2(1) default '0',
  lfsaender_knz  VARCHAR2(1) default 'N',
  verladen_am    DATE,
  verladen_um    VARCHAR2(11),
  verladen_von   VARCHAR2(4),
  verladen_von2  VARCHAR2(4),
  leer_gew       NUMBER(7,3),
  soll_gew       NUMBER(7,3),
  ist_gew        NUMBER(7,3)
)

所以你可以看到,当我在本地数据库中创建类型时,我选择了远程数据库中列的确切大小。 但是当我执行/查询流水线函数时,我收到了这个错误(抱歉是德语,但我在标题中写了英文): error message

怎么会这样?你知道有什么问题吗? 感谢任何帮助,谢谢!

编辑 2021-03-02: @ShaunPeterson 感谢您的回复,NLS_CHARACTERSET 在本地和远程数据库上都设置为 AL32UTF8。

我刚刚发现,问题似乎是由我们公司使用的 2 个不同的 IDE 引起的。 我正在使用来自全方位自动化的 PL/SQL Developer。当我在远程数据库(表“PALETTE”)上发布表规范时,我使用该 IDE 连接到远程数据库,它显示了列类型/大小,如您在我的原始帖子中所见。我重复前 6 列:

create table PALETTE
(
  pid            VARCHAR2(14) not null,
  bereich        VARCHAR2(2) not null,
  regal          VARCHAR2(2) not null,
  fach           VARCHAR2(3) not null,
  ebene          VARCHAR2(2) not null,
  vol_klasse     INTEGER,

但是当使用Oracle SQL Developer时,它看起来像这样:

CREATE TABLE "PSTEDI"."PALETTE" 
   (    "PID" VARCHAR2(14 CHAR) NOT NULL ENABLE, 
    "BEREICH" VARCHAR2(2 CHAR) NOT NULL ENABLE, 
    "REGAL" VARCHAR2(2 CHAR) NOT NULL ENABLE, 
    "FACH" VARCHAR2(3 CHAR) NOT NULL ENABLE, 
    "EBENE" VARCHAR2(2 CHAR) NOT NULL ENABLE, 
    "VOL_KLASSE" NUMBER(*,0), 

所以看起来 PL/SQL Developer 只是显示了错误的规范。我不知道为什么会这样,我想知道,但这是另一个问题。 我使用 Oracle SQL Developer 显示的列类型和大小解决了我的问题。

谢谢。

【问题讨论】:

  • 考虑对那些DB信息使用table markdown或纯文本(以防图片链接失效,至少包括一些可能重要的纯文本信息),同时用英文和纯文本重写错误信息,请勿使用图片或其他语言。
  • @T.Peter 感谢您的评论,但我用纯文本和英文写了所有重要的内容。图片是附加信息,我想读者没有它们也能理解一切。关于 DB 参数信息的 2 张图片显示 NLS_LENGTH_SEMANTICS 设置为 BYTE,我也是用纯文本写的。错误消息的图片是德语,因为我是德国人并且我的环境设置为德语。我在标题和帖子开头两次用纯文本写了错误消息:“我不断收到 ORA-06502:PL/SQL:数字或值错误:字符串缓冲区太小”。谢谢。
  • 这里在黑暗中刺了一下,因为什么都没有跳出来,但是....由于您的 NLS_LENGTH_SEMANTICS 设置为 byte 那么它可能是字符集问题。如果一个数据库具有 8 位字符集,而另一个数据库具有 16 位字符集,那么您可能会遇到此问题。要查看字符集,请使用... select * from nls_database_parameters where parameter='NLS_CHARACTERSET';
  • @ShaunPeterson 感谢您的回复,请看看我上面编辑过的帖子。

标签: oracle plsql pipelined-function


【解决方案1】:

@Dietz,你说的对我来说很好。

我遇到了和你一样的问题,不知道是不是bug。喜欢你:

  • 我在 ADT 中创建的类型与在它们各自的表列中完全相同。
  • 我设置了 NLS_LENGTH_SEMANTICS。

但是:

  • 我在 SQL Developer 中设置了默认值。
  • 我没有访问远程数据库。
  • 我不认为这与其中任何一个有关。

仅供参考,我将再尝试一件事,如果它不起作用,我将向 Oracle 支持开一张票。我将在这里更新我从 Oracle 支持中找到的内容或解决方法。

【讨论】:

    猜你喜欢
    • 2016-12-18
    • 2014-12-30
    • 1970-01-01
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    相关资源
    最近更新 更多