Error converting varchar to numeric (but there's no number) - oracle

I have a table with several columns, like this:
CREATE TABLE CRM.INFO_ADICIONAL
(
ID_INFO_ADICIONAL NUMBER(10) NOT NULL,
NOMBRE VARCHAR2(100 BYTE) NOT NULL,
OBLIGATORIO NUMBER(1) NOT NULL,
TIPO_DATO VARCHAR2(2 BYTE) NOT NULL,
ACTIVO NUMBER(1) NOT NULL,
ID_TIPO_REQUERIMIENTO NUMBER(10) NOT NULL,
ID_USUARIO_AUDIT NUMBER(10) NOT NULL,
ORDEN NUMBER(3) DEFAULT 1,
RECHAZO_POR_NO NUMBER(1),
ID_TIPO_ARCHIVO_ADJUNTO NUMBER(10),
SOLICITAR_EN VARCHAR2(30 BYTE),
ID_CONSULTA NUMBER(10),
COMBO_ID VARCHAR2(40 BYTE),
APLICAR_COMO_VENC NUMBER(1),
MODIFICABLE NUMBER(1) DEFAULT 0,
ID_AREA_GESTION NUMBER(10),
ID_TAREA NUMBER(10)
)
The "COMBO_ID" column is the target. It is defined as VARCHAR, but when I'm trying to insert a row, TOAD displays
"ORA-06502: PL/SQL: error : error de conversión de carácter a número
numérico o de valor"
Or a 'numeric conversion error', in english.
This table have some pre-existing data, and I even found some rows including values at COMBO_ID column, all of them being VARCHAR, i.e.:
NACION (Nation), SEXO (Sex), etc
I tried a few simple SELECT statements
SELECT
ID_INFO_ADICIONAL,
NOMBRE,
OBLIGATORIO,
TIPO_DATO,
ACTIVO,
ID_TIPO_REQUERIMIENTO,
ID_USUARIO_AUDIT,
ORDEN,
RECHAZO_POR_NO,
ID_TIPO_ARCHIVO_ADJUNTO,
SOLICITAR_EN,
COMBO_ID,
APLICAR_COMO_VENC,
ID_CONSULTA,
MODIFICABLE,
ID_AREA_GESTION,
ID_TAREA
INTO
pRegistro
FROM
crm.info_adicional
where pRegistro is declared as
pRegistro INFO_ADICIONAL%ROWTYPE;
Again, I'm still getting this 'numeric conversion error'.
But, wait, if I hardcode the SELECT value in COMBO_ID column with a NUMBER:
SELECT
--other columns
123456 COMBO_ID,
--other columns
INTO
pRegistro
FROM
crm.info_adicional
It works, what the heck, it's defined as VARCHAR.
If I do the same but harcoding a string, it fails to execute again
Already tried in my DEV environment, and it's working fine.
I'm not a pro in Oracle, but I feel pretty lost.
Could it be that tables get "confused"?
Any clues?

That error can also be raised if you try to push a character string that is longer than your VARCHAR2's capacity (40 in your case).
Try to check if all the data you are trying to insert is correct :
SELECT
COMBO_ID
FROM
crm.info_adicional
ORDER BY length(COMBO_ID) desc;
That would also explain why it works fine on your DEV environment which, I suppose, has different data.

Okay, I already found the answer.
Quoting Oracle Documentation:
The %ROWTYPE attribute provides a record type that represents a row in a table or view. Columns in a row and corresponding fields in a record have the same names and datatypes.
So, basically, the SELECT statement needed to be in the same order as the table columns definition.
In my case, I had a few columns (including COMBO_ID) in a different order.
Tried, re-ordering, and works like a charm.
Thank you all for the support.

Related

Oracle pipelined function: ORA-06502 numeric or value error

I wrote a pipelined function to query data from a remote database. I keep getting
ORA-06502: PL/SQL: numeric or value error: character string buffer too
small.
I think I do understand when this error would occur, for example when a table column is defined as VARCHAR2(10) and you try to insert something bigger than 10 byte. But in this case, I really don't see whats wrong.
Perhaps first I show the parameters of the local and the remote database. I think it might be important, that on both DBs NLS_LENGTH_SEMANTICS is set to BYTE.
Local DB (where the pipelined function is stored):
params local db
Remote DB (from where data is queried):
params remote db
Now the code in local 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
And this is the table specifications on remote db:
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)
)
So you can see, when I created the type in local db I choosed the exact sizes of the columns in remote db.
But when I execute/query the pipelined function, I get this error (sorry it's german, but I wrote english in title):
error message
How can this happen? Do you have any idea what's wrong?
Appreciate any help, thanks!
EDIT 2021-03-02:
#ShaunPeterson Thanks for reply, NLS_CHARACTERSET is set to AL32UTF8 on both DBs, local and remote.
I just found out, the problem seems to be caused by 2 different IDEs that are used in our company.
I am using PL/SQL Developer from allround automations. When I posted the table specifications on remote DB (table "PALETTE"), I connected to remote DB using that IDE, and it showed the column types/sizes as you can see in my original post. I repeat the first 6 columns:
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,
But when Oracle SQL Developer is used, then it looks like this:
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),
So it seems PL/SQL Developer just shows wrong specifications. I have no idea why it is like that, and I would like to know, but that's another question.
I solved my problem using the column types and sizes Oracle SQL Developer shows.
Thank you.
#Dietz, what you said was fine for me.
I'm having the same problem as you, I am wondering if it's a bug. Like you:
I created types in ADT exactly as in their respective table columns.
I set my NLS_LENGTH_SEMANTICS.
However:
I set a default in SQL Developer.
I am not accessing a remote DB.
I don't believe it's related to either of these.
FYI, I'm going to try one more thing and if it doesn't work, I'll open a ticket with Oracle Support. I will update here with what I find or workaround from Oracle Support.

Insert into not working in oracle when a single column has more characters

I have created a table as:
CREATE TABLE SHOP.EMPLOYEES
(
EMPLOYEEID NUMBER(11) NOT NULL,
LASTNAME VARCHAR2(255 BYTE) DEFAULT NULL,
FIRSTNAME VARCHAR2(255 BYTE) DEFAULT NULL,
BIRTHDATE DATE DEFAULT NULL,
PHOTO VARCHAR2(255 BYTE) DEFAULT NULL,
NOTES VARCHAR2(100 BYTE) DEFAULT NULL
)
I have column notes which has more than 100 characters.So,I tried is:
INSERT INTO shop.employees (EmployeeID, LastName, FirstName, BirthDate, Photo, Notes)
VALUES (1, 'Davolio', 'Nancy', '1968-12-08', 'EmpID1.pic', 'Education includes a BA in psychology from Colorado State University. She also completed (The Art of the Cold Call). Nancy is a member of Toastmasters International.')
But I am getting an error:
Error at line 1
ORA-01861: literal does not match format string
What could be the best datatype for those long text in Oracle?
1968-12-08 is string and you need to insert date in your table.
Conversion of string to date is needed in whenever dates are used.
There are two ways to convert your string to date.
DATE '1968-12-08'
TO_DATE('1968-12-08', 'YYYY-MM-DD')
Cheers!!
BIRTHDATE is a DATE, not a varachar, so you need to convert it:
to_date('1968-12-08', 'yyyy-mm-dd')
Obviously, you can't expect to put something as long as 300 characters into something that accepts 100 characters, can you?
But, that's not your problem. Date is. The 4th column is birthdate, its datatype is date, but you are inserting a string into it, because '1968-12-08' is a string. You should have used a date literal instead, i.e. date '1968-12-08'.
Oh, yes - back to your original question (although a wrong one in this context): best datatype for a long text. You can create a column whose datatype is VARCHAR2(4000) and it'll happily accept that "long" string you used. Or, you can even choose a CLOB which accepts up to 4 giga of characters; more than enough for you, I presume.
Finally, your query:
SQL> CREATE TABLE EMPLOYEES
2 (
3 EMPLOYEEID NUMBER(11) NOT NULL,
4 LASTNAME VARCHAR2(255 BYTE) DEFAULT NULL,
5 FIRSTNAME VARCHAR2(255 BYTE) DEFAULT NULL,
6 BIRTHDATE DATE DEFAULT NULL,
7 PHOTO VARCHAR2(255 BYTE) DEFAULT NULL,
8 NOTES VARCHAR2(100 BYTE) DEFAULT null
9 );
Table created.
Note date literal in line #4 as well as substr function in line #5 (which restricted string length to 100).
SQL> INSERT INTO employees
2 (EmployeeID, LastName, FirstName, BirthDate, Photo, Notes)
3 VALUES
4 (1, 'Davolio', 'Nancy', date '1968-12-08', 'EmpID1.pic',
5 substr('Education includes a BA in psychology from Colorado State University. She also completed (The Art of the Cold Call). Nancy is a member
of Toastmasters International.', 1, 100))
6 ;
1 row created.
SQL>
In this case I suggest simply make the NOTES column larger:
ALTER TABLE SHOP.EMPLOYEES
MODIFY (NOTES VARCHAR2(4000));
dbfiddle here
If you need something larger than this you could use the CLOB data type.

sql script not running

Here is a code snippet of a sql script which is giving me error,I have to generate a sequence on the primary_key of the table without using triggers in oracle:
CREATE SEQUENCE t1_seq START WITH 1 INCREMENT BY 1;
DROP TABLE CPR_SOURCE_SYSTEM_METADATA;
CREATE TABLE CPR_SOURCE_SYSTEM_METADATA
(
SYSTEM_ID NUMBER(4) NOT NULL t1_seq.nextval,
SYSTEM_NAME VARCHAR2(200),
DATE_FORMAT VARCHAR2(200),
CREATED_BY VARCHAR2(200),
MODIFIED_BY VARCHAR2(200),
CREATED_ON NUMBER(20),
MODIFIED_ON NUMBER(20),
IS_DELETED VARCHAR2(1),
CONSTRAINT "CPR_SOURCE_SYSTEM_PK" PRIMARY KEY ("SYSTEM_ID")
);
It is giving me the below error :
DROP TABLE CPR_SOURCE_SYSTEM_METADATA
* ERROR at line 1: ORA-00942: table or view does not exist
SYSTEM_ID NUMBER(4) NOT NULL t1_seq.nextval,
* ERROR at line 3: ORA-00907: missing right parenthesis
Not able to figure out the error,can anyone help??
SYSTEM_ID NUMBER(4) NOT NULL t1_seq.nextval,
The t1_seq.nextval segment is not valid - you cannot specify an auto-incrementing column like that.
The SQL parser is expecting to see:
SYSTEM_ID NUMBER(4) NOT NULL,
and throws the exception as the comma is not where it expects.
In Oracle 12c you can use an identity column but in earlier versions you will either need to:
Use the sequence in the SQL insert statement;
Use a trigger to insert the correct sequence value; or
Create a stored procedure to handle inserts and manage the sequence through that (disallowing direct inserts that could bypass this).

Add multiple language record in oracle database

Hi I have created a table Continent using below query
CREATE TABLE CONTINENTS
(
CONTNTCOD NUMBER(2) NOT NULL,
LOOKUPCOD VARCHAR2(20),
CONTNAM VARCHAR2(50),
CONTNAM_LCLLANG VARCHAR2(50),
);
The fourth column i.e. CONTNAM_LCLLANG is used to store data in different language.
When i tried to insert
अभिषेक it inserted something ¿¿¿¿¿¿
Select Unicode like utf8 or utf8_general_ci( in mysql ) because it support a many characters.
so, what you can do is change varchar to nvarchar
CREATE TABLE CONTINENTS
(
CONTNTCOD NUMBER(2) NOT NULL,
LOOKUPCOD VARCHAR2(20),
CONTNAM VARCHAR2(50),
CONTNAM_LCLLANG NVARCHAR2(50),
);

Oracle trigger insert to other table then modify the original table

I have theses two tables:
TABLE ASSET_ENTRY_NOTE (
ID NUMBER NOT NULL, --PK
ASSETMDL_ID NUMBER NOT NULL, --FK
DEPT_ID NUMBER NOT NULL, --FK
LOCATION NVARCHAR2(100) NOT NULL,
ASSET_ID NUMBER, --FK TO ASSETS
ACCOUNT_ID NUMBER NOT NULL, --FK
TOTAL_DPRC_DURATION FLOAT(126) NOT NULL,
TOTAL_PROD_HRS FLOAT(126),
AMORTIZATION_PRCNTG FLOAT(126),
ACQUIRE_DATE DATE NOT NULL,
DESCRIPTION NVARCHAR2(200) NOT NULL,
APPRFLAG NUMBER DEFAULT 0 NOT NULL,
WRK_HRS FLOAT(126),
)
TABLE ASSETS (
ID NUMBER NOT NULL, --PK
ASSETMDL_ID NUMBER NOT NULL, --FK
DEPT_ID NUMBER NOT NULL,
LOCATION NVARCHAR2(100) NOT NULL, --FK
ACCOUNT_ID NUMBER NOT NULL,
ACQUIRE_DATE DATE NOT NULL,
TOTAL_DPRC_DURATION FLOAT(126),
BALANCE_CLOSING_DATE DATE,
SELL_VAL FLOAT(126),
RPLCMNT_DISCOUNT FLOAT(126),
DESCRIPTION NVARCHAR2(200) NOT NULL,
)
Note that there's a one to one relationship between the two tables (i.e. ASSET_ENTRY_NOTE.ASSET_ID is Unique.
When the ASSETS_ENTRY_NOTE.APPRFLAG is updated to 1 I have this trigger that:
gets a new primary key sequence for the ASSETS table.
insert data from ASSETS_ENTRY_NOTE to ASSETS.
updates the column ASSETS_ENTRY_NOTE.ASSET_ID to the same value as the primary key value on the sequence.
This is the latest try for my trigger:
CREATE OR REPLACE TRIGGER ENTRYNT_ASSET_TRIG
after UPDATE OF APPRFLAG ON ASSET_ENTRY_NOTE
for each row
when (new.apprflag = 1)
declare
v_asset_id number;
BEGIN
SELECT assets_PK_SEQ.NEXTVAL INTO v_asset_id
FROM DUAL d;
insert into assets (ID,
assets.assetmdl_id,
assets.dept_id,
assets.location,
assets.account_id,
assets.acquire_date,
assets.total_dprc_duration,
assets.description
)
values (v_asset_id,
assetmdl_id,
dept_id,
location,
account_id,
acquire_date,
total_dprc_duration,
description
);
update ASSET_ENTRY_NOTE set asset_id = v_asset_id where ;
END;
The thing is, I know that ASSET_ENTRY_NOTE is a mutating table and the last UPDATE statement is not allowed here, But nothing else is working for me.
What I've already tried:
creating a statement-level trigger to update one value only.
using before instead of after but that's incorrect because I need the values just to insert into the ASSETS.
using a cursor to go through each value changed but I had exact fetch error.
creating a procedure that handles inserting and updating.
Any help would be appreciated.
The design seems quite strange to me, but to answer the question about the trigger:
To change the asset_entry_note row in the trigger, you need a before update trigger. In there you can just assign the value to the asset_id column.
Your insert statement is also wrong. You can table-qualify column names in the column list of an insert statement. And the values clause needs to use the values from the inserted row. You are referencing the target table's columns which is not allowed).
You also don't need a select statement to obtain the sequence value.
Putting all that together, your trigger should look something like this:
CREATE OR REPLACE TRIGGER ENTRYNT_ASSET_TRIG
BEFORE UPDATE OF APPRFLAG ON ASSET_ENTRY_NOTE
for each row
when (new.apprflag = 1)
declare
v_asset_id number;
BEGIN
v_asset_id := assets_PK_SEQ.NEXTVAL;
insert into assets
(ID,
assetmdl_id,
dept_id,
location,
account_id,
acquire_date,
total_dprc_duration,
description)
values
(v_asset_id,
new.assetmdl_id, -- reference the inserted row here!
new.dept_id,
new.location,
new.account_id,
new.acquire_date,
new.total_dprc_duration,
new.description);
new.asset_id := v_asset_id;
END;
/
You have to change the design of the application to have only one table with sign to indicate the membership of a particular entity.
Another way is to create 'after statement' trigger to update all affected rows in ASSET_ENTRY_NOTE with proper values. These rows is to be collected in, for example, package collection in row-level trigger.
I fixed it and it worked:
changed to before.
edited the update statement to an assignment of new so that the last line would become :new.asset_id := v_asset_id ;

Resources