How to fix ORA-12801 error in SQL Developer when display tables in connection browser - oracle

Using SQL Developer 18.4 MacOSX, I'm getting this error
ORA-12801: error signaled in parallel query server P000
ORA-01722:
invalid number
When I try to display the tables list in the connections tab.
I've isolated the Query.
When I execute each part of the "union all" one by one, there is no error.
when I execute the all query you got the error.
When I disable the parallel option it works fine (ALTER SESSION disable PARALLEL query).
select * from (
SELECT o.OBJECT_NAME, o.OBJECT_ID ,'' short_name, NULL partitioned,
o.sharded,
case when o.sharded <> 'Y' then o.duplicated else 'N' end duplicated,
NULL iot_type,
o.OWNER OBJECT_OWNER, o.CREATED, o.LAST_DDL_TIME, O.GENERATED, O.TEMPORARY, NULL EXTERNAL
FROM SYS.Dba_OBJECTS O
WHERE O.OWNER = :SCHEMA
AND O.OBJECT_TYPE = 'TABLE'
union all
SELECT OBJECT_NAME, OBJECT_ID , syn.SYNONYM_NAME short_NAME, NULL partitioned,
o.sharded,
case when o.sharded <> 'Y' then o.duplicated else 'N' end duplicated,
NULL iot_type,
SYN.TABLE_OWNER OBJECT_OWNER, o.CREATED, o.LAST_DDL_TIME, O.GENERATED, O.TEMPORARY, NULL EXTERNAL
FROM SYS.Dba_OBJECTS O, sys.user_synonyms syn
WHERE syn.table_owner = o.owner
and syn.TABLE_NAME = o.object_NAME
and o.object_type = 'TABLE'
and :INCLUDE_SYNS = 1
)

Related

Using IF statements in Oracle when trying to return data

How do I return data out of IF statements? I have a IF statement which is meant to return a different result dependent of the result of that statement.
IF :Value = 1 THEN
SELECT Name FROM TABLE_A
ELSEIF :Value = 2 THEN
SELECT Name FROM TABLE_B
ELSEIF :Value = 3 THEN
SELECT Name FROM TABLE_C
but this doesn't work. It expects an INTO statement in those selects. I suspect this is because Oracle can't return out of a block?
Is there a quicker way to return those select statements without creating table variables to store the data or messing around with functions?
You can do this by plain SQL:
SELECT
':Value' user_input,
CASE
WHEN ':Value' IN('a1','a2','a3')
THEN (select name from table_a)
WHEN ':Value' = 'i'
THEN (select name from table_b)
END AS output
FROM
dual
(good info about case)
If you want more than one result in your cases, then you may opt to an intelligent UNION:
SELECT t1_Col_1, t1_Col_2,'&VALUE' from TABLE_1
WHERE '&VALUE' = '1'
UNION ALL
SELECT t2_Col_1, t2_Col_2,'&VALUE' from TABLE_2
WHERE '&VALUE' = '2'
In this solution, types and number of tx_Coln must be the same.

How can we do update,delete,insert in single merge

I have a source and target table. I was doing a simple merge where I was able to do insert and update operation simultaneously. I just added columns like insert date and update date to know when the record is inserted and updated. Then, I also added a flag columns which tells us that if the record is ever updated if yes then 'Y' else 'N'. I was successful till this but when I tried to use delete it doesn't allow me.I have seen many solutions in sql server but mine is oracle. I was doing a soft delete in which the record is not deleted from the target but just the flag column is updated to 'Y' if some record is deleted from the source table. But I was not able to do that. I used case also but of no use.To be clear I just want to update flag when there is delete in source. Can anybody tell me how can I do that with single merge statement? I have simple table student having attribute like name,address mobile no , state. I have made my query like this-
merge into target t using (SELECT CASE WHEN S.STUDENT_ID IS NULL THEN T.STUDENT_ID ELSE S.STUDENT_ID END
AS STUDENT_ID,S.NAME,S.ADRESS,S.STATE,S.MOBILE FROM STUDENTS S full JOIN TARGET T ON S.STUDENT_ID=T.STUDENT_ID) s
on (s.student_id = t.student_id)
when not matched then insert (student_id,name,address,state,mobile,insert_date,update_date)
values(s.student_id,s.name,s.adress,s.state,s.mobile,sysdate,sysdate)
when matched then update set t.name=s.name,t.address=s.adress, t.state=s.state,t.mobile=s.mobile,update_date=sysdate
where s.name!=t.name or s.adress!=t.address or s.state!=t.state or s.mobile!=t.mobile;
this time I used case with every attribute and I am able to solve it but every time I run it it shows the no of extra rows present in target merged like - 4 rows are merged I dont want that can anyone help my query is-
MERGE INTO TARGET T USING (SELECT CASE WHEN S.STUDENT_ID IS NULL THEN T.STUDENT_ID ELSE S.STUDENT_ID END
AS STUDENT_ID,S.NAME,S.ADRESS,S.STATE,S.MOBILE FROM STUDENTS S FULL JOIN TARGET T ON S.STUDENT_ID=T.STUDENT_ID) S
ON (S.STUDENT_ID=T.STUDENT_ID)
WHEN NOT MATCHED THEN INSERT
(STUDENT_ID,NAME,ADDRESS,STATE,MOBILE,INSERT_DATE,UPDATE_DATE,FLAG )
VALUES(S.STUDENT_ID,S.NAME,S.ADRESS,S.STATE,S.MOBILE,SYSDATE,SYSDATE, 'N')
WHEN MATCHED THEN UPDATE SET T.FLAG='Y' , t.name = case when s.name is null then T.NAME else S.name end ,
T.ADDRESS=case when s.ADRESS is null then T.ADDRESS else S.ADRESS end ,
t.STATE=case when s.STATE is null then T.STATE else S.STATE end ,
T.MOBILE=CASE WHEN S.MOBILE IS NULL THEN T.MOBILE ELSE S.MOBILE END
WHERE S.NAME!=T.NAME OR S.ADRESS!=T.ADDRESS OR S.STATE!=T.STATE OR S.MOBILE!=T.MOBILE or t.STUDENT_ID in
(SELECT TARGET.STUDENT_ID FROM
STUDENTS FULL JOIN TARGET ON STUDENTS.STUDENT_ID=TARGET.STUDENT_ID WHERE STUDENTS.STUDENT_ID IS NULL);
Answer to my question-
MERGE INTO TARGET T USING
(SELECT CASE
WHEN S.STUDENT_ID IS NULL THEN T.STUDENT_ID
ELSE S.STUDENT_ID
END AS STUDENT_ID,
S.NAME,
S.ADRESS,
S.STATE,
S.MOBILE
FROM STUDENTS S
FULL JOIN TARGET T ON S.STUDENT_ID=T.STUDENT_ID) S ON (S.STUDENT_ID=T.STUDENT_ID) WHEN NOT MATCHED THEN
INSERT (STUDENT_ID,
NAME,
ADDRESS,
STATE,
MOBILE,
INSERT_DATE,
UPDATE_DATE,
FLAG)
VALUES(S.STUDENT_ID,
S.NAME,
S.ADRESS,
S.STATE,
S.MOBILE,
SYSDATE,
SYSDATE,
'N') WHEN MATCHED THEN
UPDATE
SET T.FLAG= CASE
WHEN ( T.STUDENT_ID IN (SELECT TARGET.STUDENT_ID
FROM STUDENTS
FULL JOIN TARGET ON STUDENTS.STUDENT_ID=TARGET.STUDENT_ID
WHERE STUDENTS.STUDENT_ID IS NULL)) THEN 'Y'
ELSE 'N'
END,
T.NAME = CASE
WHEN S.NAME IS NULL THEN T.NAME
ELSE S.NAME
END,
T.ADDRESS=CASE
WHEN S.ADRESS IS NULL THEN T.ADDRESS
ELSE S.ADRESS
END,
T.STATE=CASE
WHEN S.STATE IS NULL THEN T.STATE
ELSE S.STATE
END,
T.MOBILE=CASE
WHEN S.MOBILE IS NULL THEN T.MOBILE
ELSE S.MOBILE
END,
T.UPDATE_DATE=SYSDATE ,
T.INSERT_DATE=SYSDATE
WHERE S.NAME!=T.NAME
OR S.ADRESS!=T.ADDRESS
OR S.STATE!=T.STATE
OR S.MOBILE!=T.MOBILE
OR T.STUDENT_ID IN
(SELECT TARGET.STUDENT_ID
FROM STUDENTS
FULL JOIN TARGET ON STUDENTS.STUDENT_ID=TARGET.STUDENT_ID
WHERE STUDENTS.STUDENT_ID IS NULL)
AND FLAG!='Y';

Oracle procedure 'with query' insert into table

I have created an Oracle SQL query in TOAD which works fine. I now need to put this in a procedure.
The query has to create two counts based on different criteria (I have used With Select) and insert these plus a date and location to a table.
The query that works is
with
Selected_animals as
( SELECT TO_CHAR(SYSDATE,'DD/MM/YYYY' ) as Report_Date,
loc.name location,
count(rran.id) as Count_exported
FROM rr_animals rran,
contact con,
locations loc,
names nam
WHERE con.connum = rran.connum
AND con.loc_id = loc.id
AND con.connum = nam.connum
AND nam.name_type = 'STAND'
AND nam.dob IS NOT NULL
AND rran.sex IS NOT NULL
AND rran.web_display = 'Y'
AND rran.web_description IS NOT NULL
AND rran.visit_end_date IS NULL
AND con.loc_id IS NOT NULL
AND con.datedl IS NULL
AND rran.hold_user IS NULL
AND rran.assess_status IS NULL
AND EXISTS (SELECT rrim.id
FROM rr_images rrim
WHERE rrim.image_type = 'KENNEL'
AND rrim.rran_id = rran.id
AND DBMS_LOB.GETLENGTH(rrim.image_object) >0
AND rrim.image_object IS NOT NULL)
group by loc.NAME ),
total_animals as
(select vbav.sitename as location,
count(vbav.rran_ID) as Count_available
from v_bx_all_animal_visits vbav
where visit_end_date is null
and concat != 'DELTD'
and concat != 'DSCD'
group by vbav.sitename)
select Total_animals.location,
Selected_animals.Report_date,
Selected_animals.count_exported,
Total_animals.count_available
from Selected_animals, total_animals
where total_animals.location = selected_animals.location(+)
I have looked at several ways that seem to write the procedure but nothing seems to work. Including which was added under the CREATE or REPLACE and before BEGIN:
( o_location out bx_webstats_export_available.LOCATION%TYPE,
o_date out bx_webstats_export_available.REPORT_DATE%TYPE,
o_exported out bx_webstats_export_available.COUNT_EXPORTED%TYPE,
o_available out bx_webstats_export_available.COUNT_AVAILABLE%TYPE )
Also added after the last where statement and before End:
INSERT INTO bx_webstats_export_available(location, report_date, count_export, count_available)
values (Total_animals.location,
Selected_animals.Report_date,
Selected_animals.count_exported,
Total_animals.count_available);
Can anyone help me get this query in a Procedure please?
This is the first time I have written a Procedure from scratch and I'm struggling with it.
Many thanks,
What is it you're trying to do? Insert the results of that select into a table? If so, the following ought to suffice:
create or replace procedure your_proc_name
as
begin
insert into bx_webstats_export_available(location, report_date, count_export, count_available)
with selected_animals as (select to_char(sysdate,'DD/MM/YYYY' ) as report_date,
loc.name location,
count(rran.id) as count_exported
from rr_animals rran,
contact con,
locations loc,
names nam
where con.connum = rran.connum
and con.loc_id = loc.id
and con.connum = nam.connum
and nam.name_type = 'STAND'
and nam.dob is not null
and rran.sex is not null
and rran.web_display = 'Y'
and rran.web_description is not null
and rran.visit_end_date is null
and con.loc_id is not null
and con.datedl is null
and rran.hold_user is null
and rran.assess_status is null
and exists (select rrim.id
from rr_images rrim
where rrim.image_type = 'KENNEL'
and rrim.rran_id = rran.id
and dbms_lob.getlength(rrim.image_object) >0
and rrim.image_object is not null)
group by loc.name),
total_animals as (select vbav.sitename as location,
count(vbav.rran_id) as count_available
from v_bx_all_animal_visits vbav
where visit_end_date is null
and concat != 'DELTD'
and concat != 'DSCD'
group by vbav.sitename)
select total_animals.location,
selected_animals.report_date,
selected_animals.count_exported,
total_animals.count_available
from selected_animals, total_animals
where total_animals.location = selected_animals.location(+);
end your_proc_name;
/
If not, then please explain a bit more about the requirements you're trying to satisfy.

oracle with clause error in adodb

I am not able to use the with clause in oracle adodb connection. I have tried both wrapping the qry is a select * from (myquery) and adding a , before my with clause. All create errors.
Here is the query
`WITH TEMPa AS (select _nbr, sum(ending) as Cost from t1 group by _nbr),
TEMPB AS (select _nbr, cost,entity
from t2
where end_tms is null and sale_date is null and entity = 110)
SELECT
TEMPA._nbr
,TEMPA.cost
,TEMPb._nbr
,TEMPB._cost
,tempb.entity
,(tempb._cost - tempa.cost) as Difference
FROM TEMPA, TEMPB
WHERE TEMPA._nbr = TEMPB._nbr(+)
and tempa.cost <> tempb.cost`
Any help would be awesome!

Binding variables in dynamic PL/SQL

I have a dynamic PL/SQL that will construct the SELECT statement based on what the searching criteria input from the users,likes:
l_sql := 'SELECT * INTO FROM TABLEA WHERE 1=1 ';
IF in_param1 IS NOT NULL THEN
l_sql := l_sql || 'AND column1 = in_param1 ';
END IF;
IF in_param2 IS NOT NULL THEN
l_sql := l_sql || 'AND column2 = in_param2 ';
END IF;
...................................
IF in_paramXX IS NOT NULL THEN
l_sql := l_sql || 'AND columnXX = in_paramXX ';
END IF;
To reduce the hard parse overhead , I consider to use the binding variables. However , it is difficult to manage when supplying the actual values to the binding variables as there are so many binding variables and combination of the generated SELECT statement . I cannot use the method of DBMS_SESSION.set_context() introduced at http://www.dba-oracle.com/plsql/t_plsql_dynamic_binds.htm because my account has no right to use this package. Besides , I want the generated SQL only contains the conditions on the fields that the user did not leave empty. So I cannot change the dynamic SQL to something likes
SELECT * INTO FROM TABLEA WHERE 1=1
and ( in_param1 is NULL or column1 = in_param1)
and ( in_param2 is NULL or column2 = in_param2)
...............................................
and ( in_paramXX is NULL or columnXX = in_paramXX)
So , I want to try to use the DBMS_SQL method .Can anyone give an example about how to use DBMS_SQL to call dynamic SQL with binding variables? Especially , how can I get the result executed from DBMS_SQL.execute() to the SYS_REFCURSOR , something like :
open refcursor for select .... from
The oracle version that I use is 10g and it seems that the oracle 10g does not have DBMS_Sql.To_Refcursor()
In your Oracle version you can apply some tricks to your query in order to do this. The idea is to use a query in the following form:
select *
from
(select
:possibleParam1 as param1
-- do the same for every possible param in your query
:possibleParamN as paramN
from dual
where rownum > 0) params
inner join
-- join your tables here
on
-- concatenate your filters here
where
-- fixed conditions
then execute it with:
open c for query using param1, ..., paramN;
It works by using DUAL to generate a fake row with every single param, then inner joining this fake row to your real query (without any filters) using only the filters you want to apply. This way, you have a fixed list of bind variables in the SELECT list of the params subquery, but can control which filters are applied by modifying the join condition between params and your real query.
So, if you have something like, say:
create table people (
first_name varchar2(20)
last_name varchar2(20)
);
you can construct the following query if you just want to filter on first name
select *
from
(select
:first_name as first_name,
:last_name as last_name
from dual
where rownum > 0) params
inner join
people
on
people.first_name = params.first_name;
and this if you want to filter on both first_name and last_name
select *
from
(select
:first_name as first_name,
:last_name as last_name
from dual
where rownum > 0) params
inner join
people
on
people.first_name = params.first_name and
people.last_name = params.last_name;
and in every case you would execute with
open c for query using filterFirstName, filterLastName;
It is important for performance to use the where rownum > 0 with DUAL as it forces Oracle to "materialize" the subquery. This usually makes DUAL stop interfering with the rest of the query. Anyway, you should check the execution plans to be sure Oracle is not doing anything wrong.
In 10g a DBMS_SQL cursor can't be changed into a Ref Cursor. Going through a result set through DBMS_SQL is tortuous since, as well as looping through the rows, you also have to loop through the columns in a row.
I want the generated SQL only contains
the conditions on the fields that the
user did not leave empty
Is that purely for performance reasons ? If so, I suggest you work out what the practical execution plans are and use separate queries for them.
For example, say I'm searching on people and the parameters are first_name, last_name. gender, date_of_birth. The table has indexes on (last_name,first_name) and (date_of_birth), so I only want to allow a query if it specifies either last_name or date_of_birth.
IF :p_firstname IS NOT NULL and :p_lastname IS NOT NULL THEN
OPEN cur FOR
'SELECT * FROM PEOPLE WHERE last_name=:a AND first_name=:b AND
(date_of_birth = :c or :c is NULL) AND (gender = :d or :d IS NULL)' USING ....
ELSIF :p_lastname IS NOT NULL THEN
OPEN cur FOR
'SELECT * FROM PEOPLE WHERE last_name=:a AND
(date_of_birth = :c or :c is NULL) AND (gender = :d or :d IS NULL)' USING ....
ELSIF :p_dateofbirth IS NOT NULL THEN
OPEN cur FOR
'SELECT * FROM PEOPLE WHERE date_of_birth=:a AND
(first_name=:b OR :b IS NULL) AND (gender = :d or :d IS NULL)' USING ....
ELSE
RAISE_APPLICATION_ERROR(-20001,'Last Name or Date of Birth MUST be supplied);
END IF;

Resources