Skip to Main Content
  • Questions
  • update bulk row based on case statement

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Ankit.

Asked: August 02, 2017 - 2:56 am UTC

Last updated: August 22, 2017 - 1:04 pm UTC

Version: 12.1.0

Viewed 10K+ times! This question is

You Asked

Hello Experts,

We have a requirement as per below example,

For Example,

Need to create a procedure which fulfill below condition,

create or replace procedure
as

<declaration part>
Begin
select emp_id,emp_name,mgr_id, (case when dept_name = 'A' then 1 when dept_name = 'B' then 2 when dept_name = 'c' then 3 when mgr_id = 4 then null END) dept_id
bulk collect into lv_emp_id,lv_emp_name,lv_mgr_id,lv_dept_id
from emp,dept,manager
where
<conditions>

forall lv_dept_id.firsst .. lv_dept_id.last
update emp
set dept_id = lv_dept_id(i)
where emp_id = lv_emp_id(i) (emp_id can't be unique. it may have duplicate emp_ids also)
end;

please suggest how to update all the records based on case statement.

Thanks

and Chris said...

What's the issue here? Seems you already have basics of your code? Though I'm not sure why you need to bulk collect. Can't you do this in a single statement?

You could do this with a correlated update or merge, for example:

merge into emp e
using  (
select emp_id,(
    case when dept_name = 'A' then 1 when dept_name = 'B' then 2 when dept_name = 'c' then 3 when mgr_id = 4 then null END
) dept_id
from emp,dept,manager
where ...
) d
on    e.emp_id = d.emp_id
when matched then update 
  set e.dept_id = d.dept_id;


If you need further help with this, you must give us:

- DDL for your tables (create table)
- Sample data (insert into ...)
- The results you expect after running your query

Rating

  (15 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Ankit Bhatt, August 02, 2017 - 10:27 am UTC

create table cct_quote_parts (quote_revision_id varchar2(50),hpp_part varchar2(10),prod_type_abc varchar2(50),prod_class varchar2(50),cost_used_for_quote varchar2(50),
item_tag varchar2(50),queue_id varchar2(50))
/

create table cct_quote_revisions(revision_id varchar2(50),quote_revision varchar2(50),quote_id varchar2(50))
/
create table cct_quote (quote_id varchar2(50),opportunity_id varchar2(50),quote_number varchar2(50))
/

create table cct_opportunity (opportunity_id varchar2(50),opportunity_number varchar2(50),source_products varchar2(10))
/

insert into cct_quote_parts values (121,'Y',null,null,null,null,null,null,null)
/
insert into cct_quote_parts values (121,null,'C',null,null,null,null,null,null)
/
insert into cct_quote_parts values (121,null,null,56,null,null,null,null,null)
/
insert into cct_quote_parts values (121,null,null,192,null,null,null,null,null)
/

insert into cct_quote_revisions values (121,'0.2',1)
/

insert into cct_quote values (1,9,'Q000000066')
/

insert into cct_opportunity values (9,'OPP123',null)
/

commit;

Requirement/Results:

we need to update queue_id of cct_quote_parts table as and when new entry comes into that table. Initially queue_id column will be blank. as we have given 4 records for different conditions. For example, if hpp_part value is 'Y' then queue_id should be updated with 1, if prod_type_abc is 'C' then queue_id should be updated with 2, if prod_class is 56 then queue_id should be updated with 3, if prod_class is 192 then queue_id should be updated with 4 etc.

there may be daily 10K records to be uploaded based on different above where conditions in cct_quote_parts table and accordingly we need to update cct_quote_parts table with queue_id. There is no unique key in cct_quote_parts table.

we need to implement above requirement for all the records without impacting performance. (If it will create using procedure then its well and good)

Please suggest for any better solution approach so we can implement it.

Let us know if required more details.

Thanks.
Chris Saxon
August 03, 2017 - 9:57 am UTC

And what should the sample data you've given look like once the update is complete? What's the end result?

Ankit Bhatt, August 03, 2017 - 12:16 pm UTC

based on inserted data as per below insert statements,

insert into cct_quote_parts values (121,'Y',null,null,null,null,null,null,null)
/
insert into cct_quote_parts values (121,null,'C',null,null,null,null,null,null)
/
insert into cct_quote_parts values (121,null,null,56,null,null,null,null,null)
/
insert into cct_quote_parts values (121,null,null,192,null,null,null,null,null)

if hpp_part = 'Y' then queue_id will be updated with 1 in cct_quote_parts table
elsif prod_type_abc = 'C' then queue_id will be updated with 2 in cct_quote_parts table
elsif prod_class = 56 then queue_id will be updated with 3 in cct_quote_parts table
elsif prod_class = 192 then queue_id will be updated with 3 in cct_quote_parts table
end if;

for all above if..else conditions quote_revision_id is 121 only.

let me know if requires more details.

Chris Saxon
August 07, 2017 - 5:54 am UTC

So what have the other tables got to do with this? And why are you bulk collecting?

Surely you can do this with a case expression? Like this:

create table cct_quote_parts (
  quote_revision_id varchar2(50),hpp_part varchar2(10),prod_type_abc varchar2(50),prod_class varchar2(50),cost_used_for_quote varchar2(50), 
  item_tag varchar2(50),queue_id varchar2(50)) 
/ 

insert into cct_quote_parts values (121,'Y',null,null,null,null,null) 
/ 
insert into cct_quote_parts values (121,null,'C',null,null,null,null) 
/ 
insert into cct_quote_parts values (121,null,null,56,null,null,null) 
/ 
insert into cct_quote_parts values (121,null,null,192,null,null,null) 
/ 

update cct_quote_parts
set    queue_id = case
    when hpp_part = 'Y' then 1
    when prod_type_abc = 'C' then 2
    when prod_class = 56 then 3
    when prod_class = 192 then 3
end; 

select * from cct_quote_parts;

QUOTE_REVISION_ID  HPP_PART  PROD_TYPE_ABC  PROD_CLASS  COST_USED_FOR_QUOTE  ITEM_TAG  QUEUE_ID  
121                Y                                                                   1         
121                          C                                                         2         
121                                         56                                         3         
121                                         192                                        3

Ankit Bhatt, August 07, 2017 - 6:18 am UTC

thanks, yeah surely we can do with update statement but this update statement should execute at run time. As per given query, based on quote_number and quote_revision, we are updating queue_id as per case statement.

please let us know if required further inputs.
Chris Saxon
August 07, 2017 - 9:56 am UTC

"but this update statement should execute at run time."

I have no idea what this means. Surely all updates execute when you run them?

Ankit Bhatt, August 07, 2017 - 8:13 pm UTC

we can execute update statement at runtime but the challenge is we need to update cct_quote_parts table whenever it gets updated with different conditions and every time we can't run update statement right, so what we are expecting to create procedure which we fetch the records from below cursor and update cct_quote_parts table for all the records.

For example, before creating procedure we have tried to create anonymous block to update all the records for matching conditions but with this anonymous block, its updating the record with the same queue_ids for all the records. We want to update queue_id column based on matching conditions only,

Anonymous block:

SET SERVEROUTPUT ON;

DECLARE
CURSOR c1 IS
SELECT DISTINCT
cqp.hpp_part,
cqp.quote_revision_id,
cqp.prod_type_abc,
cqp.prod_class,
cq.opportunity_id,
co.source_products,
cqp.cost_used_for_quote,
cqp.item_tag
FROM
cct_quote_parts cqp,
cct_quote_revisions cqr,
cct_quote cq,
cct_opportunity co
WHERE
cqp.quote_revision_id = cqr.revision_id
AND
cqr.quote_id = cq.quote_id
AND
co.opportunity_id = cq.opportunity_id
AND
cqr.quote_revision = '0.1'
AND
cq.quote_number = 'Q000000066';
TYPE tb_rec IS
TABLE OF c1%rowtype;
v_tb_rec tb_rec;
l_quote_number cct_quote.quote_number%TYPE;
l_quote_revision cct_quote_revisions.quote_revision%TYPE;
l_opportunity_id cct_quote.opportunity_id%TYPE;
l_quote_revision_id cct_quote_parts.quote_revision_id%TYPE;
l_status VARCHAR2(20);
g_code VARCHAR2(100);
g_msg VARCHAR2(2000);
BEGIN
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO v_tb_rec LIMIT 1000;


FORALL i IN v_tb_rec.first .. v_tb_rec.last
UPDATE cct_quote_parts
SET
queue_id = (
CASE
WHEN v_tb_rec(i).hpp_part = 'Y' THEN 1
WHEN (
v_tb_rec(i).prod_type_abc = 'C'
OR
v_tb_rec(i).prod_type_abc = 'R'
) OR (
v_tb_rec(i).prod_class IN (
1,2,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,21,23,25,26,27,28,29,30,32,50,58,61,70,71,77,82,586,587,588,589,590,591,592,593,594,595

)
) THEN 2
WHEN (
v_tb_rec(i).prod_class IN (
56,59,62,63,287,288,289,290,291,292
)
) THEN 3
WHEN v_tb_rec(i).prod_class IN (
192,261,370
) THEN 4
WHEN (
v_tb_rec(i).cost_used_for_quote IS NULL
AND
v_tb_rec(i).source_products = 'Y'
) THEN 5
WHEN (
v_tb_rec(i).cost_used_for_quote IS NULL
AND
v_tb_rec(i).source_products = 'N'
) THEN 6
WHEN (
v_tb_rec(i).item_tag = '5'
) THEN 7
WHEN (
v_tb_rec(i).cost_used_for_quote IS NOT NULL
) THEN 8
END
)
WHERE
quote_revision_id = v_tb_rec(i).quote_revision_id;

EXIT WHEN c1%notfound;
END LOOP;

CLOSE c1;
COMMIT;
END;

You can use the same cursor query for the DDL/DML which I have shared.

Please let us know if required more details.
Chris Saxon
August 11, 2017 - 2:51 pm UTC

I don't really understand what you're trying to do. Forget the SQL for a minute. Describe in business terms what it is your doing.

Then explain how that maps to the SQL you're writing.

follow

Ankit Bhatt, August 14, 2017 - 4:49 am UTC

initially cct_quote_parts table's data has been uploaded using csv file with different business rules. once the data has been uploaded, the procedure which we have given will call and based on different business rules, it will update queue_id into cct_quote_parts tables. Business rules as per given DDL/DML statements,

1) if hpp_part = 'Y' then queue_id will update with 1
2) if prod_type_abc = 'C' then queue_id will update with 2
3) if prod_class = 56 then queue_id will update with 3
4) if prod_class = 192 then queue_id will update with 4 etc.

So for that we have written given procedure but its not updating all the inserted data for the given rules. Its updating all the records with same queue_id.

Please let us know if required more details.
Chris Saxon
August 14, 2017 - 2:25 pm UTC

So what precisely is the problem with the update I gave you earlier?

What specifically is it doing (or not doing) that makes the results incorrect?

If after running that update, you run

select * from cct_quote_parts


What precisely is wrong in the output?

followup

Ankit Bhatt, August 16, 2017 - 3:06 am UTC

The update statement which you gave was correct only but can we use the same in the procedure because as I had given explanation earlier that as soon as the file upload, the data will be inserted into cct_quote_parts table and simultaneously it should update cct_quote_parts table and queue_id should be updated with the given rules.

So is it possible for given procedure/anonymous block, if we'll use update statement in loop will it update all the records with appropriate queue_id?

Please suggest.

Thanks.
Chris Saxon
August 16, 2017 - 1:46 pm UTC

as soon as the file upload, the data will be inserted into cct_quote_parts table and simultaneously it should update cct_quote_parts table

So... run the update as soon as you upload the file? I'm not seeing the problem here?

if we'll use update statement in loop will it update all the records with appropriate queue_id?

You don't need to loop. In fact, that's a terrible idea. You want one execution to process many rows. Not many executions processing one row each.

Specify which rows you want to update in your where clause and you're done:

update cct_quote_parts
set    queue_id = case
    when hpp_part = 'Y' then 1
    when prod_type_abc = 'C' then 2
    when prod_class = 56 then 3
    when prod_class = 192 then 3
where ...find rows to change...

Ankit Bhatt, August 17, 2017 - 3:35 am UTC

thanks Chris but am I not clear properly? or my comments are confusing or misleading? What I am trying to say is there is an application where we are uploading .csv file, once the file will upload successfully, on upload button in application itself there should be DB procedure which will update each and every records with respective queue_ids and that is not one time activity, its a permanent activity.

So once the file will upload user won't ask to run the update statement hence trying to create procedure which will update the records for respective queue_ids.

please let us know if required more details.
Chris Saxon
August 17, 2017 - 10:32 am UTC

I'm still not seeing what the issue is.

So you have an upload process in your app. When your user clicks that button, it then does two things:

- Uploads the file
- Runs the update to set the values appropriately

So your code calls the upload routine, then the update. Now, the update could be in a stored procedure. So your Java/C#/whatever code calls the procedure instead of running the update itself.

But whichever you do, you run the same update. This will change all the rows the user just uploaded.

What precisely in this chain of events are you struggling to do?

followup

Ankit Bhatt, August 17, 2017 - 10:45 am UTC

yeah update statement is correct but when I use in procedure or below anonymous block, its updating all the records with same queue_id,

SET SERVEROUTPUT ON;

DECLARE
CURSOR c1 IS
SELECT DISTINCT
cqp.hpp_part,
cqp.quote_revision_id,
cqp.prod_type_abc,
cqp.prod_class,
cq.opportunity_id,
co.source_products,
cqp.cost_used_for_quote,
cqp.item_tag
FROM
cct_quote_parts cqp,
cct_quote_revisions cqr,
cct_quote cq,
cct_opportunity co
WHERE
cqp.quote_revision_id = cqr.revision_id
AND
cqr.quote_id = cq.quote_id
AND
co.opportunity_id = cq.opportunity_id
AND
cqr.quote_revision = '0.1'
AND
cq.quote_number = 'Q000000066';
TYPE tb_rec IS
TABLE OF c1%rowtype;
v_tb_rec tb_rec;
l_quote_number cct_quote.quote_number%TYPE;
l_quote_revision cct_quote_revisions.quote_revision%TYPE;
l_opportunity_id cct_quote.opportunity_id%TYPE;
l_quote_revision_id cct_quote_parts.quote_revision_id%TYPE;
l_status VARCHAR2(20);
g_code VARCHAR2(100);
g_msg VARCHAR2(2000);
BEGIN
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO v_tb_rec LIMIT 1000;


FORALL i IN v_tb_rec.first .. v_tb_rec.last
UPDATE cct_quote_parts
SET
queue_id = (
CASE
WHEN v_tb_rec(i).hpp_part = 'Y' THEN 1
WHEN (
v_tb_rec(i).prod_type_abc = 'C'
OR
v_tb_rec(i).prod_type_abc = 'R'
) OR (
v_tb_rec(i).prod_class IN (
1,2,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,21,23,25,26,27,28,29,30,32,50,58,61,70,71,77,82,586,587,588,589,590,591,592,593,594,595

)
) THEN 2
WHEN (
v_tb_rec(i).prod_class IN (
56,59,62,63,287,288,289,290,291,292
)
) THEN 3
WHEN v_tb_rec(i).prod_class IN (
192,261,370
) THEN 4
WHEN (
v_tb_rec(i).cost_used_for_quote IS NULL
AND
v_tb_rec(i).source_products = 'Y'
) THEN 5
WHEN (
v_tb_rec(i).cost_used_for_quote IS NULL
AND
v_tb_rec(i).source_products = 'N'
) THEN 6
WHEN (
v_tb_rec(i).item_tag = '5'
) THEN 7
WHEN (
v_tb_rec(i).cost_used_for_quote IS NOT NULL
) THEN 8
END
)
WHERE
quote_revision_id = v_tb_rec(i).quote_revision_id;

EXIT WHEN c1%notfound;
END LOOP;

CLOSE c1;
COMMIT;
END;

Actually it should update all the records based on respective case statement but it doesn't behave the same.

Please suggest what I need to change in my above anonymous block.

Thanks.
Chris Saxon
August 17, 2017 - 2:30 pm UTC

¯\_(ツ)_/¯

The query in cursor c1 returns nothing for the sample data you've supplied. So it updates nothing for me.

Though all the rows for quote parts have the same quote_revision_id. So each time you loop through the results, you're going to update all the rows.

If this is the case in your real data this is probably the problem. You need to find something that uniquely identifies each row.

followup

Ankit Bhatt, August 18, 2017 - 3:42 am UTC

Sorry Chris,my bad.... herewith I am sending DDL,DML & anonymous block again,

create table cct_quote_parts (quote_revision_id varchar2(50),hpp_part varchar2(10),prod_type_abc varchar2(50),prod_class varchar2(50),cost_used_for_quote varchar2(50),
item_tag varchar2(50),queue_id varchar2(50))
/

create table cct_quote_revisions (revision_id varchar2(50),quote_revision varchar2(50),quote_id varchar2(50))
/
create table cct_quote (quote_id varchar2(50),opportunity_id varchar2(50),quote_number varchar2(50))
/

create table cct_opportunity (opportunity_id varchar2(50),opportunity_number varchar2(50),source_products varchar2(10))
/

INSERT INTO cct_quote_parts VALUES (
121,
'Y',
NULL,
NULL,
NULL,
NULL,
NULL
)
/

INSERT INTO cct_quote_parts VALUES (
121,
NULL,
'C',
NULL,
NULL,
NULL,
NULL
)
/

INSERT INTO cct_quote_parts VALUES (
121,
NULL,
NULL,
56,
NULL,
NULL,
NULL,
NULL
)
/

INSERT INTO cct_quote_parts VALUES (
121,
NULL,
NULL,
192,
NULL,
NULL,
NULL
)
/

INSERT INTO cct_quote_revisions VALUES (
121,
'0.2',
1
)
/

INSERT INTO cct_quote VALUES (
1,
9,
'Q000000066'
)
/

INSERT INTO cct_opportunity VALUES (
9,
'OPP123',
NULL
)
/

COMMIT
/

Anonymous block:

SET SERVEROUTPUT ON;

DECLARE
CURSOR c1 IS
SELECT DISTINCT
cqp.hpp_part,
cqp.quote_revision_id,
cqp.prod_type_abc,
cqp.prod_class,
cq.opportunity_id,
co.source_products,
cqp.cost_used_for_quote,
cqp.item_tag
FROM
cct_quote_parts cqp,
cct_quote_revisions cqr,
cct_quote cq,
cct_opportunity co
WHERE
cqp.quote_revision_id = cqr.revision_id
AND
cqr.quote_id = cq.quote_id
AND
co.opportunity_id = cq.opportunity_id
AND
cqr.quote_revision = '0.2'
AND
cq.quote_number = 'Q000000066';

TYPE tb_rec IS
TABLE OF c1%rowtype;
v_tb_rec tb_rec;
l_quote_number cct_quote.quote_number%TYPE;
l_quote_revision cct_quote_revisions.quote_revision%TYPE;
l_opportunity_id cct_quote.opportunity_id%TYPE;
l_quote_revision_id cct_quote_parts.quote_revision_id%TYPE;
l_status VARCHAR2(20);
g_code VARCHAR2(100);
g_msg VARCHAR2(2000);
BEGIN
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO v_tb_rec LIMIT 1000;
FORALL i IN v_tb_rec.first..v_tb_rec.last
UPDATE cct_quote_parts
SET
queue_id = (
CASE
WHEN v_tb_rec(i).hpp_part = 'Y' THEN 1
WHEN (
v_tb_rec(i).prod_type_abc = 'C'
OR
v_tb_rec(i).prod_type_abc = 'R'
) OR (
v_tb_rec(i).prod_class IN (
1,2,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,21,23,25,26,27,28,29,30,32,50,58,61,70,71,77,82,586,587,588,589,590,591,592,593,594,595

)
) THEN 2
WHEN (
v_tb_rec(i).prod_class IN (
56,59,62,63,287,288,289,290,291,292
)
) THEN 3
WHEN v_tb_rec(i).prod_class IN (
192,261,370
) THEN 4
WHEN (
v_tb_rec(i).cost_used_for_quote IS NULL
AND
v_tb_rec(i).source_products = 'Y'
) THEN 5
WHEN (
v_tb_rec(i).cost_used_for_quote IS NULL
AND
v_tb_rec(i).source_products = 'N'
) THEN 6
WHEN (
v_tb_rec(i).item_tag = '5'
) THEN 7
WHEN (
v_tb_rec(i).cost_used_for_quote IS NOT NULL
) THEN 8
END
)
WHERE
quote_revision_id = v_tb_rec(i).quote_revision_id;

EXIT WHEN c1%notfound;
END LOOP;

CLOSE c1;
COMMIT;
END;

Quote_revision_is is not unique, so there will be multiple records for same quote_revision_id.

Please let me know if required more details.

Thanks.


Chris Saxon
August 21, 2017 - 11:01 am UTC

You're still updating too many rows on each pass. See the update below.

And why precisely are you using bulk processing? Why can't you use a single update?

Where clause looks too broad

paul, August 18, 2017 - 12:19 pm UTC

So for each record in your bulk collect you identify the queue_id for that record.
Then in your update statement your where clause sets the queue_id for every record that has the revision_id of the current record.

You have 4 records in cct_quote_parts all with 121 as the Quote_revision_id.

On the first record you would hit HPP_PART='Y' and set every record to queue_id=1

WHERE 
quote_revision_id = v_tb_rec(i).quote_revision_id; 


On the second record you hit PROD_TYPE_ABC and calculate a queue_id of 2. and again, update ALL the records.

repeat for the rest of the rows, updating ALL the records each time.

I think you want to add an additional condition to filter this down and update only the parts you are interested in.


Chris Saxon
August 21, 2017 - 11:02 am UTC

Yup, that looks like the issue to me.

followup

Ankit Bhatt, August 21, 2017 - 11:17 am UTC

which additional condition to add to update specific part.

could you please explain in brief?
Chris Saxon
August 21, 2017 - 4:42 pm UTC

As Paul says below, you need to tell us what the conditions are!

Or ditch the bulk collect.

Explain in Brief

paul, August 21, 2017 - 2:39 pm UTC

I don't really see anything that can be used to refine the filter to be honest.
I'm not that familiar with your data model, only you are.

In your case I don't see an attribute (column) that would allow you to go specifically from your bulk collect back to an individual row in the table based on the data you shared.

If the table is quote_parts I would expect to see a unique part number or something but that doesn't appear to be there.
So I echo what Chris says. Drop the bulk collect and update the rows directly using an update.

update cct_quote_parts
set    queue_id = case
    when hpp_part = 'Y' then 1
    when prod_type_abc = 'C' then 2
    when prod_class = 56 then 3
    when prod_class = 192 then 3
where ...find rows to change...


This way you just need to identify the rows to update (probably by QUOTE_REVISION_ID) and let the update run.

followup

Ankit Bhatt, August 22, 2017 - 2:51 am UTC

Paul, I tried that but it didn't work. I need to update the table as soon as the row comes into cct_quote_parts table.

if I can remove bulk collect from anonymous block, it is not giving desired output.

could you please help me to modify anonymous block and update the table based on queue_id conditions?

Thanks.
Chris Saxon
August 22, 2017 - 1:02 pm UTC

What does "it didn't work" mean? An ORA error? Wrong rows updated? Be precise!

RE

GJ, August 22, 2017 - 12:22 pm UTC

Ankit,
As Chris and Paul has commented the most efficient way is to use a single pass SQL statement.

If your objective is to update only those records whose queue_id is missing then you can do the following?
update cct_quote_parts
set    queue_id = case
    when hpp_part = 'Y' then 1
    when prod_type_abc = 'C' then 2
    when prod_class = 56 then 3
    when prod_class = 192 then 3
where queue_id is null




How do the records come in?

paul, August 22, 2017 - 12:56 pm UTC

You say:

"there may be daily 10K records to be uploaded based on different above where conditions in cct_quote_parts table and accordingly we need to update cct_quote_parts table with queue_id. There is no unique key in cct_quote_parts table. "

How are these records uploaded?
Maybe load them into a staging table and process that into your CCT_QUOTE_PARTS with that CASE statement populating the queue_id

If they are coming in through some other row by row process you could put this CASE statement into a trigger on that table that processes each row as it's inserted.





Chris Saxon
August 22, 2017 - 1:04 pm UTC

you could put this CASE statement into a trigger on that table that processes each row as it's inserted.

Yep. Much as I dislike this method, the update seems to be driven entirely from values within the table. So you could set the queue_id in a trigger.

More to Explore

SQL

The Oracle documentation contains a complete SQL reference.