I am using ODP.NET with EF in an MVC4 application. When performing the below operation,
_db.Set<User>().FirstOrDefault(x => x.Email == Email || x.DisplayName == DisplayName)
it throws exception
[Specified cast is not valid.] Oracle.DataAccess.Client.OracleDataReader.GetDecimal(Int32 i)
What I don't understand is that my User Object has no Int fields, I made them all decimal to smooth things over with Oracle DB.
My user table:
CREATE TABLE USERS (
USER_ID NUMBER(38) NOT NULL,
DISPLAY_NAME VARCHAR2(50 CHAR),
IS_LOCKED_OUT_FL VARCHAR2(1 CHAR),
IS_LOCKED_REASON VARCHAR2(256 CHAR),
IS_DELETED_FL VARCHAR2(1 CHAR),
EMAIL VARCHAR2(254 CHAR),
TITLE VARCHAR2(20 CHAR),
FIRSTNAME VARCHAR2(150 CHAR),
SURNAME VARCHAR2(150 CHAR),
DATECREATED DATE DEFAULT SYSDATE,
SCHEME_ID NUMBER(38),
STATUS VARCHAR2(20 CHAR) DEFAULT 'New',
PHONE VARCHAR2(20 CHAR) DEFAULT '',
PRODUCT_ID NUMBER(38) DEFAULT 0,
CONSTRAINT BCARD_USERS_PK PRIMARY KEY (USER_ID),
CONSTRAINT UK_BCARD_USERS UNIQUE (SCHEME_ID))
TABLESPACE SYSTEM
STORAGE (
INITIAL 64K
NEXT 1M
MAXEXTENTS UNLIMITED
)
I don't even know where to start debugging because the error is caused by ODP.NET and I can't step into the library. I should also mention that this doesn't happen on my 32-bit development machine, but the same code throws the exception on a 64-bit production machine
using the same 32-bit library. My project was built the target AnyCPU.
To be clear, the Int32 parameter of the GetDecimal method is the index of the column - it's throwing an error trying to convert column with index 'i'. It's not trying to convert anything to an int.
That said, my guess would be that your User object has a decimal field that's not nullable (decimal?), yet some of your columns like scheme_id and product_id allow nulls in the database.
Related
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.
I have a table like:
Table
{
...
...
SETTLEMENTDAY VARCHAR2(10 CHAR)
ACCOUNT VARCHAR2(50 CHAR)
AMOUNT NUMBER(38,5)
CURRENCY VARCHAR2(3 CHAR)
...
...
}
When I am creating View using this table I am getting the following:
View
{
...
...
SETTLEMENTDAY VARCHAR2(40 CHAR)
ACCOUNT VARCHAR2(200 CHAR)
AMOUNT NUMBER(38,5)
CURRENCY VARCHAR2(12 CHAR)
...
...
}
There is no casting.
I am using Oracle 12.2.0.1.0.
I tried to use following alter query but not helping
alter session set nls_length_semantics=CHAR;
I am not able to understand why the size is getting multiplied by 4. Which variable in database could have affected that.
Thanks,
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.
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.
I'm loading some data into oracle using an external table. One of the fields "CREATEDON" is a date but is formatted like this 20151231
How can I convert CREATEDON to a proper oracle date datatype. This is my attempt so far which doesn't work...
CREATE TABLE "AMS"."DATA"
( "BLANK" VARCHAR2(255 BYTE),
"BLANK2" VARCHAR2(255 BYTE),
"CLIENT" VARCHAR2(255 BYTE),
"MATERIAL" DATE,
"CREATEDON" VARCHAR2(255 BYTE)
)
ORGANIZATION EXTERNAL
( TYPE ORACLE_LOADER
DEFAULT DIRECTORY "DIR"
ACCESS PARAMETERS
( records delimited BY '\r\n'
skip 1
fields terminated BY '|' lrtrim missing field VALUES are NULL
)
LOCATION ( "DIR":'foo.txt' )
)
REJECT LIMIT UNLIMITED ;
You have two options:
Keep as is, and transform in your select statements, such as:
select ..., to_date(CREATEDON,'YYYYMMDD') CREATEDON
Define the format in the table DDL:
"CREATEDON" VARCHAR2(255 BYTE) DATE_FORMAT DATE MASK "YYYYMMDD"