Bulk bind truncated bind ошибка числа или значения

There is a difference between LONG ROW in PL/SQL and SQL.

In SQL:

http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements001.htm

«Raw binary data of variable length up to 2 gigabytes.»

In PL/SQL:

http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/datatypes.htm#i10924

»
You use the LONG RAW datatype to store binary data or byte strings. LONG RAW data is like LONG data, except that LONG RAW data is not interpreted by PL/SQL. The maximum size of a LONG RAW value is 32760 bytes.
«

See example below:

SQL> desc t
 Имя                                       Пусто?   Тип
 ----------------------------------------- -------- ----------------------------
 X                                                  LONG RAW

CREATE OR REPLACE PACKAGE BS_SAMPLES AS
  TYPE type_memo_raw IS TABLE OF LONG RAW;
  PROCEDURE MIGRATE_MEMO_TO_MEMO_CLOB(RMEMO OUT  type_memo_raw);
END BS_SAMPLES;

CREATE OR REPLACE PACKAGE BODY BS_SAMPLES AS
  PROCEDURE MIGRATE_MEMO_TO_MEMO_CLOB (RMEMO OUT  type_memo_raw)
  AS
  ls_memo_raw      type_memo_raw;
  BEGIN

        SELECT t.x BULK COLLECT
        INTO ls_memo_raw 
        FROM t;     

        RMEMO := ls_memo_raw;
   End MIGRATE_MEMO_TO_MEMO_CLOB;
END BS_SAMPLES;

OK, now I added 1 row to T table and put into X column the image (using PL/SQL Developer tool) what has about 90K size.

SQL> declare
  2   a BS_SAMPLES.type_memo_raw;
  3  begin
  4     BS_SAMPLES.MIGRATE_MEMO_TO_MEMO_CLOB(a);
  5  end;
  6  /
declare
*
error in line 1:
ORA-06502: PL/SQL: : Bulk Bind: Truncated Bind 
ORA-06512: at  "SCOTT.BS_SAMPLES", line 7 
ORA-06512: at  line 4 


SQL> alter table t modify (x blob);

SQL> select dbms_lob.getlength(x) a from t;

                             a
------------------------------                                                  
                         90025 

Ok, let’s now re-create table T and add the image with about 29K size — all will work:

SQL> declare
  2   a BS_SAMPLES.type_memo_raw;
  3  begin
  4     BS_SAMPLES.MIGRATE_MEMO_TO_MEMO_CLOB(a);
  5  end;
  6  /

PL/SQL procedure completed.

SQL> alter table t modify (x blob);

SQL> select dbms_lob.getlength(x) a from t;

                             a                                                  
------------------------------                                                  
                         25554 

So LONG ROW should be converted to BLOB and this is the best way to handle it.

Are you getting an ORA-06502 error message when working with Oracle SQL? Learn how to resolve it and what causes it in this article.

ORA-06502 Cause

The cause of the “ORA-06502 PL/SQL numeric or value error” can be one of many things:

  1. A value is being assigned to a numeric variable, but the value is larger than what the variable can handle.
  2. A non-numeric value is being assigned to a numeric variable.
  3. A value of NULL is being assigned to a variable which has a NOT NULL constraint.

Let’s take a look at the solutions for each of these causes.

The solution for this error will depend on the cause.

Let’s see an example of each of the three causes mentioned above.

Solution 1: Value Larger than Variable (Number Precision Too Large)

In this example, we have some code that is setting a numeric variable to a value which is larger than what can be stored.

Let’s create this procedure which declares and then sets a variable:

CREATE OR REPLACE PROCEDURE TestLargeNumber
AS
  testNumber NUMBER(3);
BEGIN
  testNumber := 4321;
END;

If we compile it, it compiles with no errors.

Procedure TESTLARGENUMBER compiled

Now, let’s run the procedure.

EXEC TestLargeNumber;

We get an error:

Error starting at line : 8 in command -
EXEC TestLargeNumber
Error report -
ORA-06502: PL/SQL: numeric or value error: number precision too large
ORA-06512: at "SYSTEM.TESTLARGENUMBER", line 5
ORA-06512: at line 1
06502. 00000 -  "PL/SQL: numeric or value error%s"
*Cause:    An arithmetic, numeric, string, conversion, or constraint error
           occurred. For example, this error occurs if an attempt is made to
           assign the value NULL to a variable declared NOT NULL, or if an
           attempt is made to assign an integer larger than 99 to a variable
           declared NUMBER(2).
*Action:   Change the data, how it is manipulated, or how it is declared so
           that values do not violate constraints.

The error we’ve gotten is “ORA-06502: PL/SQL: numeric or value error: number precision too large”. It also includes an ORA-06512, but that error just mentions the next line the code is run from, as explained in this article on ORA-06512.

This is because our variable testNumber can only hold 3 digits, because it was declared as a NUMBER(3). But, the value we’re setting it to a few lines later is 4 digit long (4321).

So, the value is too large for the variable.

To resolve it, increase the size of your variable, or manipulate your value to fit the size of the variable (if possible).

In our example , we can change the size of the variable.

CREATE OR REPLACE PROCEDURE TestLargeNumber
AS
  testNumber NUMBER(4);
BEGIN
  testNumber := 4321;
END;
Procedure TESTLARGENUMBER compiled

Now, let’s run the procedure.

EXEC TestLargeNumber;
PL/SQL procedure successfully completed.

The procedure runs successfully. We don’t get any output (because we didn’t code any in), but there are no errors.

Read more on the Oracle data types here.

While you’re here, if you want an easy-to-use list of the main features in Oracle SQL, get my SQL Cheat Sheet here:

Solution 2: Non-Numeric Value

Another way to find and resolve this error is by ensuring you’re not setting a numeric variable to a non-numeric value.

For example, take a look at this function.

CREATE OR REPLACE PROCEDURE TestNonNumeric
AS
  testNumber NUMBER(4);
BEGIN
  testNumber := 'Yes';
END;
Procedure TESTNONNUMERIC compiled

The procedure compiles successfully. Now, let’s fun the function.

EXEC TestNonNumeric;
Error starting at line : 8 in command -
EXEC TestNonNumeric
Error report -
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at "SYSTEM.TESTNONNUMERIC", line 5
ORA-06512: at line 1
06502. 00000 -  "PL/SQL: numeric or value error%s"
*Cause:    An arithmetic, numeric, string, conversion, or constraint error
           occurred. For example, this error occurs if an attempt is made to
           assign the value NULL to a variable declared NOT NULL, or if an
           attempt is made to assign an integer larger than 99 to a variable
           declared NUMBER(2).
*Action:   Change the data, how it is manipulated, or how it is declared so
           that values do not violate constraints.

The error we get is “ORA-06502: PL/SQL: numeric or value error: character to number conversion error”.

This happens because our variable testNumber is set to a NUMBER, but a few lines later, we’re setting it to a string value which cannot be converted to a number

To resolve this error:

  1. Ensure the value coming in is a number and not a string.
  2. Convert your string to a number using TO_NUMBER (the conversion might happen implicitly but this may help).
  3. Convert your string to the ASCII code that represents the string using the ASCII function.
  4. Change the data type of your variable (but check that your code is getting the right value first).

The solution you use will depend on your requirements.

Solution 3: NOT NULL Variable

This error can appear if you try to set a NULL value to a NOT NULL variable.

Let’s take a look at this code here:

CREATE OR REPLACE PROCEDURE TestNonNull
AS
  testNumber NUMBER(4) NOT NULL := 10;
  nullValue NUMBER(4) := NULL;
BEGIN
  testNumber := nullValue;
END;

Procedure TESTNONNULL compiled

Now, the reason we’re using a variable to store NULL and not just setting testNumber to NULL is because we get a different error in that case. Besides, it’s probably more likely that your NULL value will come from another system or a database table, rather than a hard-coded NULL value.

Let’s run this function now.

Error starting at line : 9 in command -
EXEC TestNonNull
Error report -
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "SYSTEM.TESTNONNULL", line 6
ORA-06512: at line 1
06502. 00000 -  "PL/SQL: numeric or value error%s"
*Cause:    An arithmetic, numeric, string, conversion, or constraint error
           occurred. For example, this error occurs if an attempt is made to
           assign the value NULL to a variable declared NOT NULL, or if an
           attempt is made to assign an integer larger than 99 to a variable
           declared NUMBER(2).
*Action:   Change the data, how it is manipulated, or how it is declared so
           that values do not violate constraints.

We get the ORA-06502 error.

This error message doesn’t give us much more information. But, we can look at the code on line 6, as indicated by the message. We can see we have a variable that has a NOT NULL constraint, and the variable is NULL.

To be sure, we can output some text in our demo when it is null.

CREATE OR REPLACE PROCEDURE TestNonNull
AS
  testNumber NUMBER(4) NOT NULL := 10;
  nullValue NUMBER(4) := NULL;
BEGIN
  IF (nullValue IS NULL) THEN
    dbms_output.put_line('Value is null!');
  ELSE
    testNumber := nullValue;
  END IF;
END;

Now let’s call the procedure.

EXEC TestNonNull;
Value is null!

The output shows the text message, indicating the value is null.

ORA-06502 character string buffer too small

This version of the error can occur if you set a character variable to a value larger than what it can hold.

When you declare character variables (CHAR, VARCHAR2, for example), you need to specify the maximum size of the value. If a value is assigned to this variable which is larger than that size, then this error will occur.

For example:

DECLARE
  charValue VARCHAR2(5);
BEGIN
  charValue := 'ABCDEF';
END;

If I compile this code, I get an error:

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

This happens because the variable is 5 characters long, and I’m setting it to a value which is 6 characters long.

You could also get this error when using CHAR data types.

DECLARE
  charValue CHAR(5);
BEGIN
  charValue := 'A';
  charValue := charValue || 'B';
END;
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 5

This error happens because the CHAR data type uses the maximum number of characters. It has stored the value of A and added 4 space characters, up until its maximum value of 5.

When you try to concatenate a value of B to it, the resulting value is ‘A    B’, which is 6 characters.

To resolve this, use a VARCHAR2 variable instead of a CHAR, and ensure the maximum size is enough for you.

ORA-06502: pl/sql: numeric or value error: null index table key value

Sometimes you might get this error message with the ORA-06502 error:

ORA-06502: pl/sql: numeric or value error: null index table key value

This means that either:

  • Your index variable is not getting initialized, or
  • Your index variable is getting set to NULL somewhere in the code.

Check your code to see that neither of these two situations are happening.

ORA-06502: pl/sql: numeric or value error: bulk bind: truncated bind

You might also get this specific error message:

ORA-06502: pl/sql: numeric or value error: bulk bind: truncated bind

This is caused by an attempt to SELECT, UPDATE, or INSERT data into a table using a PL/SQL type where a column does not have the same scale as the column in the table.

For example, you may have declared a variable in PL/SQL to be VARCHAR2(100), but your table is only a VARCHAR2(50) field. You may get this error then.

You may also get this error because some data types in PL/SQL have different lengths in SQL.

To resolve this, declare your variables as the same type as the SQL table:

type t_yourcol is table of yourtable.yourcol%TYPE;

So, that’s how you resolve the ORA-06502 error.

While you’re here, if you want an easy-to-use list of the main features in Oracle SQL, get my SQL Cheat Sheet here:

You need to write each CLOB value out into a separate file, and include that file name as part of the main data record. Something like this:

declare
  data_file utl_file.file_type;
  clob_file utl_file.file_type;
  buffer varchar2(32767);
  position pls_integer;
  chars pls_integer;

  myquery varchar2(4000) := 'select column1 ||''~''|| column3, '
    || '''column2_'' || rownum, column2 from mytable';
  mycursor sys_refcursor;
  myresult varchar2(4000);
  myfilename varchar2(120);
  myclob clob;
begin
  data_file := utl_file.fopen ('D42', 'mydata', 'w');
  open mycursor for myquery; 
  loop
    fetch mycursor into myresult, myfilename, myclob;
    exit when mycursor%notfound;
    if myclob is not null and dbms_lob.getlength(myclob) > 0 then
      myresult := myresult ||'~'|| myfilename;
      clob_file := utl_file.fopen ('D42', myfilename, 'w', 32767);
      position := 1;
      chars := 32767;
      while position < dbms_lob.getlength(myclob) loop
        dbms_lob.read(myclob, chars, position, buffer);
        utl_file.put(clob_file, buffer);
        utl_file.fflush(clob_file);
        position := position + chars;
      end loop;
      utl_file.fclose(clob_file);
    end if;
    utl_file.put_line(data_file, myresult);
  end loop;
  close mycursor;
  utl_file.fclose(data_file);
end;
/

There is one data_file which has all the non-CLOB data, including the name of the individual file you write that row’s CLOB to. The filename can be anything as long as it’s unique; I’ve used rownum but you can use the row’s primary key ID if it has one, for example.

With a dummy table created as:

create table mytable (column1 number, column2 clob, column3 varchar2(10));
insert into mytable (column1, column2, column3) values (1, null, 'First');
insert into mytable (column1, column2, column3) values (2, 'Second CLOB', 'Second');
insert into mytable (column1, column2, column3) values (3, 'Third CLOB', 'Third');

.. this creates mydata containing:

1~First
2~Second~column2_2
3~Third~column2_3

and files column2_2 and column2_3 with the corresponding CLOB values.

Then if I run SQL*Loader with that data file and the CLOB files available, and control file:

load data
characterset UTF8
truncate
into table mytable2
fields terminated by "~"
trailing nullcols
(
  column1 char(10),
  column3 char(10),
  clob_filename filler char(120),
  column2 lobfile(clob_filename) terminated by EOF
)

… the new table is populated as:

select * from mytable2;

   COLUMN1 COLUMN2                        COLUMN3  
---------- ------------------------------ ----------
         1                                First      
         2 Second CLOB                    Second
         3 Third CLOB                     Third

(I still think you should be doing this with the built-in tools, data pump or just copying data internally between two schemas, as discussed on previous questions…)

Bulk Bind: Truncated bind

I recently had a good reminder on one of the subtleties of PL/SQL bulk fetches and inserts. I kept getting this error on the FETCH:

ORA-06502: PL/SQL: numeric or value error: Bulk Bind: Truncated Bind  

The procedure purpose is to bulk insert data from a temporary staging table to the real, properly-sized column Load table.  Simple, right?  Except when I use the wrong table types.

My problem?

The elements I was selecting in my cursor did not logically fit into the table type target of my cursor fetch.

I defined my cursor using a query on the temporary staging table (larger VARCHAR2 columns), not the real table (exact-fit VARCHAR2, NUMBER and DATE columns).
But, I defined my table type to receive the cursor results on my real table:


CURSOR c_dl IS
SELECT ...
...
...
FROM my_staging_table stg
WHERE action IN ( 'INSERT','UPDATE');
TYPE my_load_table_tt IS TABLE OF my_load_table%ROWTYPE
INDEX BY PLS_INTEGER;
load_data_arr my_load_table_tt;


BEGIN
OPEN c_dl;
LOOP
FETCH c_dl BULK COLLECT INTO load_data_arr LIMIT 1000; ----- Error  happens here!
FORALL ii IN 1 .. load_data_arr.COUNT
INSERT INTO my_load_table
...
...

The Bulk Bind: Truncated Bind error is because the cursor – with bigger elements, cannot logically fit in the defined array/table type – the columns are too big.

To correct this, I changed the definition of the table type to be a table of the staging table. Then the FETCH proceeds fine, as does the INSERT.

But wait, why didn’t the INSERT fail, since I am Inserting from a (potentially) large-column cursor into the exact-fit table?

The INSERT proceeds because the elements being inserted fit  – the transforms and validations (processed previous to this point in the code) have ensured that all elements are indeed the size they should be in the exact-fit table.  So the INSERT does not complain.

LOG ERRORS REJECT LIMIT UNLIMITED

Now, IF one column in one row was too large, or the wrong format for a date, the entire INSERT would have failed. Unless I used the LOG ERRORS clause, which I did.

IF one or more records is/are bad, I want to load all the good records, and single out the bad. To do this, I used the LOG ERRORS REJECT LIMIT UNLIMITED clause at the end of the INSERT statement:

INSERT INTO my_load_table
VALUES ( ..load_data_arr(ii).col1,
load_data_arr(ii).col2,
load_data_arr(ii).col3,
...
load_data_arr(ii).coln)
LOG ERRORS REJECT LIMIT UNLIMITED;

This LOG ERRORS REJECT LIMIT UNLIMITED clause ensures that all clean rows will insert, and all “bad” rows get logged to an error table, in my case called ERR$MY_LOAD_TABLE.

I created the error log table previously, using the command:
BEGIN
DBMS_ERRLOG.create_error_log (dml_table_name => 'MY_LOAD_TABLE');
END;

We define the staging tables with generous VARCHAR2s on purpose. We want to allow leeway in the incoming data, knowing we can strip punctuation, perform lookups, format dates, and perform other transformations in the validation stage. That means doing all that validation is on us, to make sure the data is in shape for the final insert. Just one way of doing things – there are many other approaches.

My reminder is – especially when writing things quickly – to pay attention to the nuances of the features in use.  I won’t make that mistake for a while now :).

For a full treatment of bulk processing with BULK COLLECT and FORALL, see Steve Feuerstein’s article PL/SQL 101: Bulk Processing with BULK COLLECT and FORALL.

ORA-06502: PL/SQL: numeric or value error: Bulk Bind: Truncated Bind

Filed under: PL/SQL — hourim @ 3:18 pm

Have you ever been faced to the above error?  I mean this bizarre Bulk Bind: Truncated Bind?  This is a strange and unclear error message. Let me put you in the context that gave me this error. I am trying to load data into an 11gR2 (11.2.0.3.0) database from data coming via a db link from a 10gR2 (10.2.0.5.0). This is not more as what I have simplified to the maximum here below

11gR2> begin
2   for x in (
3    select v2_col
4    from  distant_table
5    )
6   loop
7     null;
8  end loop;
9  end;
10  /

begin
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: Bulk Bind: Truncated Bind
ORA-06512: at line 2

And if instead I issue a straightforward select from a SQL windows

11gR2>
select v2_col
from  distant_table;

I have no errors.

I was struggling with this issue until one of my smart colleagues puts me into the right direction: there is a difference in the character set between the 11g (multi-byte) and the 10g database (single byte) as shown below

11gR2> select * from nls_database_parameters;
PARAMETER                      VALUE
------------------------------ ----------------------------
NLS_CHARACTERSET               AL32UTF8    --> here multibyte
NLS_LENGTH_SEMANTICS           CHAR        --> here
NLS_NCHAR_CHARACTERSET         AL16UTF16
NLS_RDBMS_VERSION              11.2.0.3.0

10gR2> select * from nls_database_parameters;

PARAMETER                      VALUE
------------------------------ ------------------------------------
NLS_CHARACTERSET               WE8ISO8859P1  --> here single byte
NLS_LENGTH_SEMANTICS           BYTE          --> here
NLS_NCHAR_CHARACTERSET         AL16UTF16
NLS_RDBMS_VERSION              10.2.0.5.0

I was thinking that the 11gR2 PL/SQL engine (because still I am not fetching anything explicitly, I am just selecting) could recognize this character set difference between the local and the distant database and implicitly declare its local variable so that it could have enough space to contain incoming column when this one will have special characters .

Having smart colleagues is always a lucky situation, because not only my colleague pointed me to the right direction but gave me a workaround that I am pleased to reproduce here below :

11gR2> begin
2   for x in (
3    select v2_col ||''
4    from  distant_table
5    )
6   loop
7     null;
8  end loop;
9  end;
10  /

PL/SQL procedure successfully completed.

The work around consists of concatenating the distant column v2_col with a null string. This magically overcome the Bulk Bind: Truncated Bind error (don’t tell me why the PL/SQL engine can overcome this error when I have used such a concatenation).

If you have already been faced to this error then I will be pleased to know how you managed to solved it

Возможно, вам также будет интересно:

  • Builtin function or method python ошибка
  • Build gradle android studio ошибка
  • Build 23 project zomboid ошибка
  • Bugsplat ошибка killing floor 2 что это
  • Bugsplat ошибка company of heroes 2

  • Понравилась статья? Поделить с друзьями:
    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии