00917. 00000 - "missing comma" in Oracle - sql

INSERT INTO PatientTbl(sysID,id,name,dob,phone,hospVisits(hostChg,vDate,refDoc,docChg))
VALUES('P002','491221019V','Dulani Perera','3-FEB-49',
phone_arr_ty(0112233211),hospVisitsNt_ty_tbl(hospVisits_ty(75.00,'25-MAY-06',
(SELECT REF(d) FROM DoctorTbl d WHERE d.regNo=2342111322),550.00)),
hospVisitsNt_ty_tbl(hospVisits_ty(90.00,'29-MAY-06',(SELECT REF(d) FROM DoctorTbl d
WHERE d.regNo=2344114344),300.00)
)
);/
When I'm trying to run above query it will generate following error.
Error starting at line : 65 in command -
INSERT INTO PatientTbl(sysID,id,name,dob,phone,hospVisits(hostChg,vDate,refDoc,docChg)) VALUES('P002','491221019V','Dulani Perera','3-FEB-49', phone_arr_ty(0112233211),
hospVisitsNt_ty_tbl(hospVisits_ty(75.00,'25-MAY-06',(SELECT REF(d) FROM DoctorTbl d WHERE d.regNo=2342111322),550.00)),
hospVisitsNt_ty_tbl(hospVisits_ty(90.00,'29-MAY-06',(SELECT REF(d) FROM DoctorTbl d WHERE d.regNo=2344114344),300.00))
)
Error at Command Line : 65 Column : 58
Error report -
SQL Error: ORA-00917: missing comma
00917. 00000 - "missing comma"
*Cause:
*Action:
I think there shouldn't be issue in commas. How to solve this ?

The error is being raised at the opening parenthesis of the nest table type:
INSERT INTO PatientTbl(sysID,id,name,dob,phone,hospVisits(hostChg, ...
^
Your PatientTbl has a nested table column. You seem to be trying to specify the details of that table's object type inside the insert statement, which isn't correct.
Assuming that nest table column is called hospVisits you would just do:
INSERT INTO PatientTbl(sysID,id,name,dob,phone,hospVisits)
VALUES('P002','491221019V','Dulani Perera','3-FEB-49',
phone_arr_ty(0112233211),hospVisitsNt_ty_tbl(hospVisits_ty(75.00,'25-MAY-06',
(SELECT REF(d) FROM DoctorTbl d WHERE d.regNo=2342111322),550.00)),
hospVisitsNt_ty_tbl(hospVisits_ty(90.00,'29-MAY-06',(SELECT REF(d) FROM DoctorTbl d
WHERE d.regNo=2344114344),300.00)
)
);
But your nested table construction is wrong too; you are trying to use two separate hospVisitsNt_ty_tbl with a single hospVisits_ty in each, rather than a single hospVisitsNt_ty_tbl with multiple hospVisits_ty:
INSERT INTO PatientTbl(sysID,id,name,dob,phone,hospVisits)
VALUES('P002','491221019V','Dulani Perera',date '1949-02-03',
phone_arr_ty(0112233211),
hospVisitsNt_ty_tbl(
hospVisits_ty(75.00, date '2006-05-25',
(SELECT REF(d) FROM DoctorTbl d WHERE d.regNo=2342111322),550.00),
hospVisits_ty(90.00,date '2006-05-29',
(SELECT REF(d) FROM DoctorTbl d WHERE d.regNo=2344114344),300.00)
)
);
I've also switched to using ANSI date literals, on the assumption (and hope) that those columns are actually dates not strings. You were relying on NLS parameters, which you don't usually have control over, and implicit date conversion is not a good idea as it can fail when other people run your code.
You will get unexpected results even in your own environment because you're using 2-digit years; the string '3-FEB-49' would be implicit converted to 2049, not 1949 (which is looks like you would expect):
alter session set nls_date_format = 'DD-MON-RR';
select to_char(to_date('3-FEB-49'), 'YYYY-MM-DD') from dual;
TO_CHAR(TO
----------
2049-02-03
And that's if your defaut model has RR, RRRR or YY; if it happens to have YYYY then you'd get 0049-02-03.
Object build and insertion tested with some made-up data types, as you haven't provided yours:
create type doctor_ty as object (regNo number)
/
create table DoctorTbl of doctor_ty
/
create type hospVisits_ty as object (hostChg number,vDate date,
refDoc ref doctor_ty,docChg number)
/
show errors
create type hospVisitsNt_ty_tbl as table of hospVisits_ty
/
create type phone_arr_ty as object (num number)
/
create table PatientTbl(sysID varchar2(4),id varchar2(12),name varchar2(30),dob date,
phone phone_arr_ty,hospVisits hospVisitsNt_ty_tbl)
nested table hospVisits store as hospVisitsNt return as locator;
/
INSERT INTO PatientTbl(sysID,id,name,dob,phone,hospVisits)
VALUES('P002','491221019V','Dulani Perera',date '1949-02-03',
phone_arr_ty(0112233211),
hospVisitsNt_ty_tbl(
hospVisits_ty(75.00, date '2006-05-25',
(SELECT REF(d) FROM DoctorTbl d WHERE d.regNo=2342111322),550.00),
hospVisits_ty(90.00,date '2006-05-29',
(SELECT REF(d) FROM DoctorTbl d WHERE d.regNo=2344114344),300.00)
)
);
1 row inserted.

Related

ORA-01722: invalid number when a specific number 112 is used

WITH
TEST_RESULT_CTE AS
(SELECT R.DSDW_RESULT_ID,
R.PARAM_VALUE AS TEST_ID
FROM SLIMS_POC_RESULT_DETAIL R
JOIN SLIMS_POC_PARAMETER P ON P.PARAM_ID=R.PARAM_ID
WHERE P.PARAMETER_NAME='TEST_ID' AND P.CATEGORY = 'Result' )
SELECT * FROM
(
SELECT S.SAMPLE_ID, R.DSDW_RESULT_ID, PARA.PARAMETER_NAME as PNAME, R.PARAM_VALUE as PVALUE
FROM SLIMS_POC_RESULT_DETAIL R
JOIN TEST_RESULT_CTE TR ON TR.DSDW_RESULT_ID = R.DSDW_RESULT_ID
JOIN SLIMS_POC_TEST T ON T.TEST_ID = TR.TEST_ID
JOIN SLIMS_POC_SAMPLE S ON S.SAMPLE_ID = T.SAMPLE_ID --AND S.SAMPLE_ID = to_char(113)
JOIN SLIMS_POC_PARAMETER PARA ON PARA.PARAM_ID=R.PARAM_ID AND PARA.CATEGORY='Result'
)
Result_Data
PIVOT
(
MAX(PVALUE) FOR PNAME IN ( 'TEST_ID', 'RESULT_NAME', 'UNIT', 'RESULT_TEXT', 'VALUE', 'STATUS', 'ENTERED_ON', 'ENTERED_BY', 'RESULT_TYPE' )
) PIVOTED_TAB
WHERE SAMPLE_ID > 111
ORDER BY SAMPLE_ID;
The above sql Query provides an output, without any error.
However if I replace '111' with '112' in WHERE cluase, I get the following error:
ORA-01722: invalid number
01722. 00000 - "invalid number"
*Cause: The specified number was invalid.
*Action: Specify a valid number.
This error is quite strange to me, and that's why tough to fix.
The error is most likely from the data that is being returned from your new sample_id. There is a string being converted to a number that is failing. Check your data for invalid numerical data in varchar columns. Note that it could be an implicit conversion, not necessarily one where you are doing a to_number() call.

How to insert values from a subquery in merge sentence

I want to insert into a merge statement of a stored procedure at ORACLE a value that comes from a subquery. How can I do that? This is what I design but it doesn't work.
CREATE OR REPLACE PROCEDURE P_FORMULARIO
IS
BEGIN
MERGE INTO HT_FORMULARIO d
USING
(SELECT id, METODO_ID, TIPO_ID, DEPARTAMENTO_ID, EQUIPAMEINTO_ID, FECHAINICIO
FROM ODS_FORMULARIO) o
ON (d.ID_CAMPO = o.id)
WHEN MATCHED THEN
UPDATE SET d.SK_METODO_MUEST = o.METODO_ID,
d.SK_TIPO_MUESTRA = o.TIPO_ID,
d.SK_DEPARTAMENTO = o.DEPARTAMENTO_ID,
d.SK_EQUIPAMIENTO = o.EQUIPAMEINTO_ID
WHEN NOT MATCHED THEN
INSERT (ID_CAMPO, SK_METODO_MUEST, SK_TIPO_MUESTRA, SK_DEPARTAMENTO, SK_EQUIPAMIENTO)
VALUES (o.id, o.METODO_ID, o.TIPO_ID,o.DEPARTAMENTO_ID, o.EQUIPAMEINTO_ID,
(select SK_FECHA from dt_fecha where mes = MONTH( o.FECHAINICIO) and anio = YEAR(o.FECHAINICIO));
COMMIT;
END P_EQUIPAMIENTO;
I don't know if that is possible, thanks for the help.
There are some things wrong in your procedure
The subselect below the insert does not make any sense, as you have only five fields in the insert clause and five values in the values section.
You are getting all the records from ODS_FORMULARIO that are matching with the target table HT_FORMULARIO based on the ID, then use that part to get the values of year and month there.
It is not clear whether you want to do with year and month. Those are java in-build funtions, not SQL.
The insert misses a field.
Your functions don't work in SQL:
SQL> select month(sysdate) from dual ;
select month(sysdate) from dual
*
ERROR at line 1:
ORA-00904: "MONTH": invalid identifier
SQL> select year(sysdate) from dual ;
select year(sysdate) from dual
*
ERROR at line 1:
ORA-00904: "YEAR": invalid identifier
Keep in mind the way to get this year and month from your dt_fecha table, some options you might have for that are:
SQL> select to_char(sysdate,'Month') from dual ;
TO_CHAR(SYSDATE,'MONTH')
------------------------------------
October
SQL> select to_char(sysdate,'YYYY') from dual ;
TO_C
----
2021
SQL> select extract(month from sysdate) from dual ;
EXTRACT(MONTHFROMSYSDATE)
-------------------------
10
SQL> select extract(year from sysdate) from dual ;
EXTRACT(YEARFROMSYSDATE)
------------------------
2021
Then you have the column MES in the table DT_FECHA. If you have the month store with the name, you need to use NLS_LANGUAGE to get the right name according to your language. Example, in German
SQL> select TO_CHAR(SYSDATE,'fmDay, DD Month YYYY', 'NLS_DATE_LANGUAGE=''GERMAN''') from dual;
TO_CHAR(SYSDATE,'FMDAY,DDMONTHYYYY','NLS_DATE_LANGUAGE=''GERMAN''')
--------------------------------------------------------------------------------
Samstag, 16 Oktober 2021
Having say that, you want to refactor the merge and use a join in the source part of the statement to get there the sk_fecha value.
Important: Remember that I am assuming some things, like the month is stored in Spanish but not in uppercase. If it is stored in uppercase, use the function upper before to_char. If it is in another language, use the proper nls_language. If the month is stored as a number, then you can use to_char with 'MM' or extract as in my example above
CREATE OR REPLACE PROCEDURE P_FORMULARIO
IS
begin
MERGE INTO HT_FORMULARIO d
USING
(SELECT
odsf.id,
odsf.METODO_ID,
odsf.TIPO_ID,
odsf.DEPARTAMENTO_ID,
odsf.EQUIPAMEINTO_ID,
odsf.FECHAINICIO,
to_char(odsf.FECHAINICIO,'Month', 'NLS_DATE_LANGUAGE=''SPANISH''') as Month,
to_char(odsf.FECHAINICIO,'YYYY') as Year ,
dtf.sk_fecha
FROM ODS_FORMULARIO odsf
join dt_fecha dft on dtf.mes = odsf.mes and dtf.anio = odsf.year ) o
ON (d.ID_CAMPO = o.id)
WHEN MATCHED THEN
UPDATE SET d.SK_METODO_MUEST = o.METODO_ID,
d.SK_TIPO_MUESTRA = o.TIPO_ID,
d.SK_DEPARTAMENTO = o.DEPARTAMENTO_ID,
d.SK_EQUIPAMIENTO = o.EQUIPAMEINTO_ID
WHEN NOT MATCHED THEN
INSERT (ID_CAMPO, SK_METODO_MUEST, SK_TIPO_MUESTRA, SK_DEPARTAMENTO, SK_EQUIPAMIENTO , --a field here is missing--)
VALUES (o.id, o.METODO_ID, o.TIPO_ID,o.DEPARTAMENTO_ID, o.EQUIPAMEINTO_ID, o.SK_FECHA );
COMMIT;
END P_EQUIPAMIENTO;

ORA-22992 / ORA-06502+ORA-06512 errors

I'm using this part of code in large one :
SELECT DISTINCT
P.SKU, SUBSTR(X.ATTRIBUTENAME, 14, 3) ATTRIBUTECODE, X.ATTRIBUTEVALUE
FROM
PRODUCT#ISPSTAG2 P,
XMLTABLE('/attrs/attr'
PASSING XMLTYPE(REGEXP_REPLACE(P.ATTRIBUTES_DE_AT, '<attr name="longDescription">.*?<\/attr>'))
COLUMNS ATTRIBUTENAME VARCHAR2(50) PATH '#name',
ATTRIBUTEVALUE VARCHAR2(4000) PATH '/string'
) X
WHERE X.ATTRIBUTENAME LIKE 'Z_CA%'
AND DN(DOMAINID) = 'AT'
AND SKU NOT LIKE 'OFF_%' AND SKU NOT LIKE 'PDT%'
AND ATTRIBUTES_DE_AT IS NOT NULL;
And it throws an ORA-22992 error.
I've made some research and a tip can to use the dual
SELECT DISTINCT P.SKU, SUBSTR(X.ATTRIBUTENAME, 14, 3) ATTRIBUTECODE, X.ATTRIBUTEVALUE
FROM PRODUCT#ISPSTAG2 P,
XMLTABLE('/attrs/attr'
PASSING XMLTYPE(REGEXP_REPLACE(P.ATTRIBUTES_DE_AT, '<attr name="longDescription">.*?<\/attr>'))
COLUMNS ATTRIBUTENAME VARCHAR2(50) PATH '#name',
ATTRIBUTEVALUE VARCHAR2(4000) PATH '/string'
) X
WHERE X.ATTRIBUTENAME LIKE 'Z_CA%'
AND DN(DOMAINID) = 'AT'
AND SKU NOT LIKE 'OFF_%' AND SKU NOT LIKE 'PDT%'
AND (SELECT ATTRIBUTES_DE_AT FROM DUAL) IS NOT NULL;
But now I get ORA-06502/ORA-06512 errors :
ORA-06502: PL/SQL : erreur numérique ou erreur sur une valeur
ORA-06512: à "SYS.XMLTYPE", ligne 272
ORA-06512: à ligne 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.
But, I executed the first one on ISPSTAG2 and it works, but the second one on ISPSTAG2 returns me the same ORA-06502/ORA-06512 errors so the issue is with the dual subquery.
I also tried to create a view on ISPSTAG2 using DBMS_LOB.SUBSTR with 4000 characters but same error.
Any ideas ? Thank you.
If forgot to use the (SELECT ATTRIBUTES_DE_AT FROM DUAL) subquery inside the XMLTYPE...
SELECT DISTINCT P.SKU, SUBSTR(X.ATTRIBUTENAME, 14, 3) ATTRIBUTECODE, X.ATTRIBUTEVALUE
FROM PRODUCT#ISPSTAG2 P,
XMLTABLE('/attrs/attr'
PASSING XMLTYPE(REGEXP_REPLACE(**(SELECT ATTRIBUTES_DE_AT FROM DUAL)**, '<attr name="longDescription">.*?<\/attr>'))
COLUMNS ATTRIBUTENAME VARCHAR2(50) PATH '#name',
ATTRIBUTEVALUE VARCHAR2(4000) PATH '/string'
) X
WHERE X.ATTRIBUTENAME LIKE 'Z_CA%'
AND DN(DOMAINID) = 'AT'
AND SKU NOT LIKE 'OFF_%' AND SKU NOT LIKE 'PDT%'
AND (SELECT ATTRIBUTES_DE_AT FROM DUAL) IS NOT NULL;
The thing I don't understand is that when don't use the subquery in the IS NOT NULL filter I have the the ORA-22992 error (using distant LOB), so why I have a different error not using the dual subquery, which is the same distant LOB ?
Anyway for you for your time/help :)

How to Insert data using cursor into new table having single column containing XML type data in Oracle?

I'm able to insert values into table 2 from table 1 and execute the PL/SQL procedure successfully but somehow the output is clunky. I don't know why?
Below is the code :
create table airports_2_xml
(
airport xmltype
);
declare
cursor insert_xml_cr is select * from airports_1_orcl;
begin
for i in insert_xml_cr
loop
insert into airports_2_xml values
(
xmlelement("OneAirport",
xmlelement("Rank", i.Rank) ||
xmlelement("airport",i.airport) ||
xmlelement("Location",i.Location) ||
xmlelement("Country", i.Country) ||
xmlelement("Code_iata",i.code_iata) ||
xmlelement("Code_icao", i.code_icao) ||
xmlelement("Total_Passenger",i.Total_Passenger) ||
xmlelement("Rank_change", i.Rank_change) ||
xmlelement("Percent_Change", i.Percent_change)
));
end loop;
end;
/
select * from airports_2_xml;
Output:
Why it is showing &lt ,&gt in the output ? And why am I unable to see the output fully?
Expected output:
<OneAirport>
<Rank>3</Rank>
<Airport>Dubai International</Airport>
<Location>Garhoud</Location>
<Country>United Arab Emirates</Country>
<Code_IATA>DXB</Code_IATA>
<Code_ICAO>OMDB</Code_ICAO>
<Total_passenger>88242099</Total_passenger>
<Rank_change>0</Rank_change>
<Percent_Change>5.5</Percent_Change>
</OneAirport>
The main issue is how you are constructnig the XML. You have an outer XMLElement for OneAirport, and the content of that element is a single string.
You are generating individual XMLElements from the cursor fields, but then you are concenating those together, which gives you a single string which still has the angle brackets you're expecting. So you're trying to do something like, simplified a bit:
select
xmlelement("OneAirport", '<Rank>1</Rank><airport>Hartsfield-Jackson</airport>')
from dual;
XMLELEMENT("ONEAIRPORT",'<RANK>1</RANK><AIRPORT>HARTSFIELD-JACKSON</AIRPORT>')
--------------------------------------------------------------------------------
<OneAirport><Rank>1</Rank><airport>Hartsfield-Jackson</airp
and by default XMLElement() escapes entities in the passed-in values, so the angle-brackets are being converted to 'safe' equivalents like <. If it didn't do that, or you told it not to with noentityescaping:
select xmlelement(noentityescaping "OneAirport", '<Rank>1</Rank><airport>Hartsfield-Jackson</airport>')
from dual;
XMLELEMENT(NOENTITYESCAPING"ONEAIRPORT",'<RANK>1</RANK><AIRPORT>HARTSFIELD-JACKS
--------------------------------------------------------------------------------
<OneAirport><Rank>1</Rank><airport>Hartsfield-Jackson</airport></OneAirport>
then that would appear to be better, but you still actually have a single element with a single string (with characters that are likely to cause problems down the line), rather than the XML structure you almost certainly intended.
A simple way to get an zctual structure is with XMLForest():
xmlelement("OneAirport",
xmlforest(i.Rank, i.airport, i.Location, i.Country, i.code_iata,
i.code_icao, i.Total_Passenger, i.Rank_change, i.Percent_change)
)
You don't need the cursor loop, or any PL/SQL; you can just do:
insert into airports_2_xml (airport)
select xmlelement("OneAirport",
xmlforest(i.Rank, i.airport, i.Location, i.Country, i.code_iata,
i.code_icao, i.Total_Passenger, i.Rank_change, i.Percent_change)
)
from airports_1_orcl i;
The secondary issue is the display. You'll see more data if you issue some formatting commands, such as:
set lines 120
set long 32767
set longchunk 32767
Those will tell your client to retrieve and show more of the long (XMLType here) data, rather the default 80 characters it's giving you now.
Once you are generating a nested XML structure you can use XMLSerialize() to display that more readable when you query your second table.
Try this below block :
declare
cursor insert_xml_cr is select * from airports_1_orcl;
v_airport_xml SYS.XMLTYPE;
begin
for i in insert_xml_cr
loop
SELECT XMLELEMENT ( "OneAirport",
XMLFOREST(i.Rank as "Rank"
,i.airport as "Airport"
,i.Location as "Location"
,i.Country as "Country"
,i.code_iata as "Code_iata"
,i.code_icao as "code_icao"
,i.Total_Passenger as "Total_Passenger"
, i.Rank_change as "Rank_change"
,i.Percent_change as "Percent_Change"
))
into v_airport_xml
FROM DUAL;
insert into airports_2_xml values (v_airport_xml);
end loop;
end;

Error: ORA-06550 in Oracle 10g

Here i have created a package,with package specification and package body,which contains a procedure which insert a row in table,package creation is successful but execution of that package is giving me error
ORA-06550
Package specification:
create or replace package pkgEmp --package specification created..
as
procedure insertEmp(eno number,name varchar2,job varchar2,mgr varchar2,salary number);
end pkgEmp;
package body:
create or replace package body pkgEmp
as
procedure insertEmp(eno number,name varchar2,job varchar2,mgr varchar2,salary number)
is
begin
insert into emp values(eno,name,job,mgr,salary);
end insertEmp;
end pkgEmp;
Exeuting procedure insertEmp:
begin
pkgEmp.insertEmp(&eno,&name,&job,&mgr,&salary); --i m trying to get data in run time.
End;
and output:
ORA-06550: line 2, column 18:
PLS-00103: Encountered the symbol "&" when expecting one of the following:
( ) - + case mod new not null others
table avg count current exists max min prior sql stddev sum
variance execute multiset the both leading trailing forall
merge year month DAY_ hour minute second timezone_hour
timezone_minute timezone_region timezone_abbr time timestamp
interval date
1. begin
2. pkgEmp.insertEmp(&eno,&name,&job,&mgr,&salary);
3. End;
Why I am not able to get data from User,I m using SQL*Plus
I think you need to put parameters in 'single quotes' like '&name' where the datatype is non-integer.
Thanks,
Aditya