Search a value in Oracle VARRAY collection - oracle

I have an Oracle table that has a column of type VARRAY Oracle collection type.
create or replace
TYPE FUSION_USER.FUSION_KEY_LIST AS VARRAY(20) OF VARCHAR2(80);
CREATE TABLE FUSION_QUEUE_AUDIT
(
"XML_ID" NUMBER NOT NULL ENABLE,
"XML_MESSAGE_TYPE" NUMBER(4,0) NOT NULL ENABLE,
"XML_MESSAGE" SYS.XMLTYPE,
"KEY_ID" NUMBER,
"KEY_LIST" FUSION_USER.FUSION_KEY_LIST,
"STATUS_IND" VARCHAR2(1 BYTE) NOT NULL ENABLE
);
The data in KEY_LIST column is stored as:
FUSION_USER.FUSION_KEY_LIST(1600458446,N)
FUSION_USER.FUSION_KEY_LIST(1600488742,N)
FUSION_USER.FUSION_KEY_LIST(1600481496,N)
FUSION_USER.FUSION_KEY_LIST(1600473344,N)
How do I search for a value in this column?. The below queries throws an error:
select * from fusion_queue_audit where xml_message_type = 560 and create_date > (sysdate - 8/24) and INSTR(key_list,'1600103836') > 0;
OR
select * from fusion_queue_audit where xml_message_type = 560 and create_date > (sysdate - 8/24) and key_list like '%1600103836%';
Thanks in advance
R

You can apply table to the collection to access and filter its content like
select * from fusion_queue_audit
where xml_message_type = 560
and create_date > (sysdate - 8/24)
and exists (
select 1 from table(key_list) t1
where t1.column_value like '%1600103836%'
);
Check the test example on fiddle

Related

Different Output with same Input for ORACLE MD5 Function

At a given time I stored the result of the following ORACLE SQL Query :
SELET col , TO_CHAR( LOWER( STANDARD_HASH( col , 'MD5' ) ) AS hash_col FROM MyTable ;
A week later, I executed the same query on the same data ( same values for column col ).
I thought the resulting hash_col column would have the same values as the values from the former execution but it was not the case.
Is it possible for ORACLE STANDARD_HASH function to deliver over time the same result for identical input data ?
It does if the function is called twice the same day.
All we have about the data changing (or not) and the hash changing (or not) is your assertion.
You could create and populate a log table:
create table hash_log (
sample_time timestamp,
hashed_string varchar2(200),
hashed_string_dump varchar2(200),
hash_value varchar2(200)
);
Then on a daily basis:
insert into hash_log values
(select systimestamp,
source_column,
dump(source_column),
STANDARD_HASH(source_column , 'MD5' )
from source_table
);
Then, to spot changes:
select distinct hashed_string ||
hashed_string_dump ||
hash_value
from hash_log;

Dynamic tablename in teradata create statement

I am trying to create a dynamic table name using the following procedure in WhereScape RED:
SELECT CAST(CURRENT_DATE as format 'YYYYMMDD') into v_date;
SET v_tname = 'Anirban_Test' || v_date ||'030' ;
CREATE MULTISET TABLE [TABLEOWNER].[(SELECT * from v_tname)] NO FALLBACK ,
NO BEFORE JOURNAL,
NO AFTER JOURNAL,
CHECKSUM = DEFAULT,
DEFAULT MERGEBLOCKRATIO
(
TARGET_JOB_NAME VARCHAR(50) CHARACTER SET LATIN NOT CASESPECIFIC NOT NULL)
UNIQUE PRIMARY INDEX UP_LOAD_PROTOCOL ( TARGET_JOB_NAME );
But the create statement is not working. Any help will be appreciated.

ORA-00932: inconsistent datatypes

I'm trying to CAST MULTISET an object via PL/SQL and I'm getting the error mentioned in the subject.
I've checked the datatypes defined in the object itself and the columns in the tables and they appear to match. Same goes for the order I get the values and the order in the object.
But I keep getting the error, here is the full code:
CREATE OR REPLACE TYPE TASK_DESTINATION_LIST_OBJTYP AS OBJECT
(
ENTITY_ID NUMBER(9)
,ENTITY_CODE NUMBER(3)
,ENTITY_NAME VARCHAR2(255)
,ENTITY_FAVOTIRE NUMBER(1)
,ENTITY_PATH VARCHAR2(1535)
,STATE_CODE NUMBER(3)
,STATE_NAME VARCHAR2(50)
,RES_MSG VARCHAR2(2000)
)
/
CREATE TYPE TASK_DESTINATION_LIST_COLTYP AS TABLE OF TASK_DESTINATION_LIST_OBJTYP
The Query:
SELECT Decode (tsk_info_t.dest_dev_id,NULL,
tsk_info_t.dest_srv_id,
tsk_info_t.dest_dev_id) AS entity_id,
Decode (tsk_info_t.dest_dev_id,
NULL,1,3) AS entitytyp_code,
Decode (tsk_info_t.dest_dev_id,NULL,
tsk_info_t.dest_srv_name,
tsk_info_t.dest_dev_name) AS entity_name,
(
SELECT Count(*)
FROM pref_info_t
WHERE Nvl (dev_id, 0) = Nvl (tsk_info_t.dest_dev_id, 0)
AND srv_id = tsk_info_t.dest_srv_id) AS entity_favotire,
Decode (tsk_info_t.dest_dev_id,NULL,
(
SELECT path
FROM entity_path_view
WHERE dev_id IS NULL
AND srv_id = tsk_info_t.dest_srv_id),
(
SELECT path
FROM entity_path_view
WHERE dev_id = dest_dev_id
AND srv_id = dest_srv_id)) AS entity_path,
tsk_info_t.state_code AS state_code,
(
SELECT state_type_name
FROM ref_state_type
WHERE state_type_code = state_code ) AS state_name,
tsk_info_t.res_msg AS res_msg
FROM tsk_info_t
WHERE tsk_info_t.tsk_id = 5957
ORDER BY tsk_info_t.dest_srv_name,
tsk_info_t.dest_dev_name ASC)
AS task_destination_list_coltyp )
AS destination_list

Cursor for loop using a selection instead of a table ( Oracle )

I'm writing a procedure to fill up a child table from a parent table. The child table however has more fields than the parent table ( as it should be ). I've conjured a cursor which point to a selection, which is essentially a join of multiple tables.
Here's the code I got so far :
CREATE OR REPLACE PROCEDURE Pop_occ_lezione
AS
x Lezione%rowtype;
CURSOR cc IS
WITH y as(
SELECT Codice_corso,
nome_modulo,
Data_inizio_ed_modulo diem,
Giorno_lezione,
ora_inizio_lezione o_i,
ora_fine_lezione o_f,
anno,
id_cdl,
nome_sede,
locazione_modulo loc
FROM lezione
join ( select id_cdl, anno, codice_corso from corso ) using (codice_corso)
join ( select codice_corso, locazione_modulo from modulo ) using (codice_corso)
join ( select nome_sede, id_cdl from cdl ) using (id_cdl)
WHERE
case
when extract (month from Data_inizio_ed_modulo) < 9 then extract (year from Data_inizio_ed_modulo) - 1
else extract (year from Data_inizio_ed_modulo)
end = extract (year from sysdate+365)
)
SELECT *
FROM y
WHERE sem_check(y.diem,sysdate+365) = 1;
--
BEGIN
FETCH cc into x;
EXIT when cc%NOTFOUND;
INSERT INTO Occr_lezione
VALUES (
x.Codice_corso,
x.Nome_modulo,
x.diem,x.giorno_lezione,
x.Ora_inizio_lezione,
to_date(to_char(next_day(sysdate,x.Giorno_lezione),'DD-MM-YYYY') || to_char(x.Ora_inizio_lezione,' hh24:mi'),'dd-mm-yyyy hh24:mi'),
to_date(to_char(next_day(sysdate,x.Giorno_lezione),'DD-MM-YYYY') || to_char(x.Ora_fine_lezione,' hh24:mi'),'dd-mm-yyyy hh24:mi'),
x.nome_sede,
0,
x.loc
);
END LOOP;
END;
/
But of course it won't work, because the variable x has the type of my initial table row, which has less columns then my selection. Unfortunately As far as I know a rowtype variable is needed to cycle trough a cursor, in order to fetch data from it. Can you see the contradiction? How can I change the code? Is there a certain type of variable which can be crafted to reflect a row from my query result? Or maybe a way to cycle trough the data in the cursor without using a support variable? Or maybe something entirely different? Please let me know.
Ok, so as suggested I tried something like this:
INSERT INTO Occr_lezione(
Codice_corso,
Nome_modulo,
Data_inizio_ed_modulo,
Giorno_lezione,
Ora_inizio_lezione,
Ora_fine_lezione,
Anno,
Id_cdl,
Nome_sede,
Locazione_modulo
)
WITH y as(
SELECT Codice_corso,
Nome_modulo,
Data_inizio_ed_modulo,
Giorno_lezione,
Ora_inizio_lezione,
Ora_fine_lezione,
Anno,
Id_cdl,
Nome_sede,
Locazione_modulo
FROM Lezione
join ( select Id_cdl, Anno, Codice_corso from Corso ) using (codice_corso)
join ( select Codice_corso, Locazione_modulo from Modulo ) using (Codice_corso)
join ( select Nome_sede, Id_cdl from Cdl ) using (id_cdl)
WHERE
case
when extract (month from Data_inizio_ed_modulo) < 9 then extract (year from Data_inizio_ed_modulo) - 1
else extract (year from Data_inizio_ed_modulo)
end = extract (year from sysdate+365)
)
SELECT *
FROM y
WHERE sem_check(y.Data_inizio_ed_modulo,sysdate+365) = 1;
END;
/
But it says PL/SQL: ORA-00904: "LOCAZIONE_MODULO": invalid identifier
which isn't true, because the query return a table in which such column is present... am I missing something?
The code is compiled with no errors, it occurs when I try to fire the procedure.
In the table Occr_lezione as you can see:
CREATE TABLE Occr_lezione (
Codice_corso varchar2(20) NOT NULL,
Nome_modulo varchar2(50) NOT NULL,
Data_inizio_ed_modulo date NOT NULL,
Giorno_lezione number(1) NOT NULL,
Ora_inizio_lezione date NOT NULL,
Data_inizio_occr_lezione date,
Data_fine_occr_lezione date NOT NULL,
Nome_sede varchar2(30) NOT NULL,
Num_aula varchar2(3) NOT NULL,
Tipo_aula varchar2(20) NOT NULL,
--
CONSTRAINT fk_Occr_lezione_lezione FOREIGN KEY (Codice_corso,Nome_modulo,Data_inizio_ed_modulo,Giorno_lezione,Ora_inizio_lezione) REFERENCES Lezione(Codice_corso,Nome_modulo,Data_inizio_ed_modulo,Giorno_lezione,Ora_inizio_lezione) ON DELETE CASCADE,
CONSTRAINT fk_Occr_lezione_aula FOREIGN KEY (Nome_sede,Num_aula,Tipo_aula) REFERENCES Aula(Nome_sede,Num_aula,Tipo_aula) ON DELETE SET NULL,
CONSTRAINT pk_Occr_lezione PRIMARY KEY (Codice_corso,Nome_modulo,Data_inizio_ed_modulo,Giorno_lezione,Ora_inizio_lezione,Data_inizio_occr_lezione),
CHECK ( trunc(Data_inizio_occr_lezione) = trunc(Data_fine_occr_lezione) ), -- data inizio = data fine // prenotazione giornaliera
CHECK ( Data_inizio_occr_lezione < Data_fine_occr_lezione ) -- ora inizio < ora fine // coerenza temporale
there is not a column named Locazione_modulo, however the last column Tipo_aula as the same type and size of Locazione modulo :
CREATE TABLE Modulo (
Codice_corso varchar2(20) NOT NULL,
Nome_modulo varchar2(50),
Locazione_modulo varchar2(20) NOT NULL,
--
CONSTRAINT fk_Modulo_Corso FOREIGN KEY(Codice_corso) REFERENCES Corso(Codice_corso) ON DELETE CASCADE,
CONSTRAINT pk_Modulo PRIMARY KEY(Codice_corso,Nome_modulo),
CHECK (Locazione_modulo IN ('Aula','Laboratorio','Conferenze'))
);
So it should be irrelevant, right?
If you really want to use explicit cursors, you can declare x to be of type cc%rowtype
CREATE OR REPLACE PROCEDURE Pop_occ_lezione
AS
CURSOR cc IS ...
x cc%rowtype;
...
Unless you are using explicit cursors because you want to be able to explicitly fetch the data into local collections that you can leverage later on in your procedure, code using implicit cursors tends to be preferrable. That eliminates the need to FETCH and CLOSE the cursor or to write an EXIT condition and it implicitly does a bulk fetch to minimize context shifts.
BEGIN
FOR x IN cc
LOOP
INSERT INTO Occr_lezione ...
END LOOP;
END;
Of course, in either case, I would hope that you'd choose more meaningful names for your local variables-- x and cc don't tell you anything about what the variables are doing.
If all you are doing is taking data from one set of tables and inserting it into another table, it would be more efficient to write a single INSERT statement rather than coding a PL/SQL loop.
INSERT INTO Occr_lezione( <<column list>> )
SELECT <<column list>>
FROM <<tables you are joining together in the cursor definition>>
WHERE <<conditions from your cursor definition>>

ORA-01722: invalid number when executing query through pro*C

I am facing ORA-1772: invalid number again and again when the query is run through pro*c file. Same query works fine when executed directly on pl/sql developer.
SELECT queue_entry_id ,queue_urgency,
TO_CHAR (chg_dt, 'MM-DD-YY'),
TO_CHAR (queue_after_dt, 'MM-DD-YY'),
chg_who ,
upd_cnt FROM BSD_QUEUE_WORK WHERE queue_entry_id IN (
SELECT queue_entry_id FROM (
SELECT /*+ INDEX (bsd_queue_work bsd_q_wrk_dt_idx) */
BSD_QUEUE_WORK.queue_entry_id
FROM BSD_QUEUE_WORK WHERE BSD_QUEUE_WORK.queue_after_dt <= SYSDATE
order by BSD_QUEUE_WORK.queue_urgency DESC, BSD_QUEUE_WORK.queue_after_dt)
WHERE rownum <=20) FOR UPDATE;
Old query looked like -
SELECT
/*+ INDEX (bsd_queue_work bsd_q_wrk_dt_idx) +*/
BSD_QUEUE_WORK.queue_entry_id,
TO_CHAR(BSD_QUEUE_WORK.chg_dt,:b0) ,
TO_CHAR( BSD_QUEUE_WORK.queue_after_dt,:b0) ,
BSD_QUEUE_WORK.chg_who ,
BSD_QUEUE_WORK.upd_cnt
FROM BSD_QUEUE_WORK
WHERE (BSD_QUEUE_WORK.queue_after_dt<=SYSDATE
AND ROWNUM <=:b2)
ORDER BY BSD_QUEUE_WORK.queue_urgency DESC BSD_QUEUE_WORK.queue_after_dt FOR UPDATE
This query was first selecting 20 rows and then sorting them on queue_urgency. This lead to high urgency rows waiting long for their turn if we had total of 10k rows. And, User wanted to find out high queue_urgency rows first and process them in chunks of 20 rows. Hence, I created the new query which is giving errors as above.
Table structure is as-
SQL> desc bsd_queue_work
Name Null? Type
----------------------------------------- -------- ----------------------------
QUEUE_ENTRY_ID NOT NULL NUMBER(18)
QUEUE_AFTER_DT NOT NULL DATE
UPD_CNT NOT NULL NUMBER(6)
CHG_WHO NOT NULL VARCHAR2(32)
CHG_DT NOT NULL DATE
QUEUE_URGENCY NOT NULL NUMBER(38)

Resources