Oracle Update statement with if conditions - oracle

I'm trying to merge three update statements into one.
"UPDATE DOT_WORKS SET START_DATE = :StartDate WHERE ID = :WorksId and END_DATE IS NULL;"
"UPDATE DOT_WORKS SET WORKS_TYPE = :WorksType WHERE ID = WorksId and WORKS_GROUP = :WorksGroup;"
"UPDATE DOT_WORKS SET WORKS_CONNECTION = :WorksConn WHERE ID = WorksId and WORKS_PLACE = :WorksPlace;"
I'm wondering whether there is a way to do that.
The reason why I'm trying to do so is to save the calls to database. It's more efficient to call db once instead of three.
Thanks!

UPDATE DOT_WORKS
SET START_DATE = case when END_DATE IS NULL then :StartDate else START_DATE end,
WORKS_TYPE = case when WORKS_GROUP = :WorksGroup then :WorksType else WORKS_TYPE end,
WORKS_CONNECTION = case when WORKS_PLACE = :WorksPlace then :WorksConn else WORKS_CONNECTION end
WHERE ID = :WorksId
and
(
END_DATE IS NULL OR
WORKS_GROUP = :WorksGroup OR
WORKS_PLACE = :WorksPlace
)

Related

Unexpected NULL in multi-column correlated update

I want to run a multi-column correlated update of this kind:
UPDATE t1 t1_alias
SET (table_name, tablespace_name) = (
SELECT table_name, tablespace_name
FROM t2 t2_alias
WHERE t1_alias.table_name = t2_alias.table_name
);
But my attempt:
update customer up
set (customer_name, account, active) = (
select tmp.name, tmp.account, case when tmp.active = 'Yes' then 1 else 0 end
from customer_temp tmp
where up.agent = substr(tmp.agent, -4) and up.customer_code = tmp.code
);
... throws:
ORA-01407: cannot update ("FOO"."CUSTOMER"."CUSTOMER_NAME") to NULL
The source table customer_temp has no null values so I must be getting matches wrong. What is my error or misconception?
Presumably, there are some rows in the target table that have no match in the subquery.
You can avoid this with by adding an exists condition that filters out "unmatched" rows:
update customer up
set (customer_name, account, active) = (
select tmp.name, tmp.account, case when tmp.active = 'Yes' then 1 else 0 end
from customer_temp tmp
where up.agent = substr(tmp.agent, -4) and up.customer_code = tmp.code
)
where exists (
select 1
from customer_temp tmp
where up.agent = substr(tmp.agent, -4) and up.customer_code = tmp.code
);

How to improve the performance of the SQL query?

I have Sql Queries where in due to which it's effecting the performance of the package.
ln_trans_type_id is the variable declared.
UPDATE invoice_table xai
SET process_flag = 'E',
error_description = 'Invoice Number Does not Exists '
WHERE xai.process_flag = 'N'
AND NOT EXISTS (
SELECT 1
FROM ra_customer_trx_all rct
WHERE rct.org_id = 1001
AND rct.trx_number = xai.invoice_number
AND rct.cust_trx_type_id = ln_trans_type_id
);
kindly please review and advise.
Without an execution plan we can only guess. You should compare the performance with NOT IN but make sure the subquery doesn't return any NULL values, otherwise you won't get any hits.
UPDATE invoice_table xai
SET process_flag = 'E',
error_description = 'Invoice Number Does not Exists '
WHERE xai.process_flag = 'N'
AND xai.invoice_number
NOT IN (
SELECT rct.trx_number
FROM ra_customer_trx_all rct
WHERE rct.org_id = 2326
AND rct.trx_number is not null -- important!
AND rct.cust_trx_type_id = ln_trans_type_id
);
If you inside a package declare a variable (as tempVar) and pass later to update
SELECT 1 into tempVar FROM
ra_customer_trx_all rct , invoice_table xai
WHERE rct.org_id = 1001 AND rct.trx_number = xai.invoice_number AND rct.cust_trx_type_id = ln_trans_type_id

Trigger on one table field works for all table fields

I have a trigger which is for a few fields in a table. But for some reason, if another field is changed (which is not defined in trigger) then it still fires.
CREATE OR REPLACE TRIGGER INTEGRATION_EMPLOYMENT
AFTER UPDATE OF start_day_of_employment, end_of_employment ON hr_employment_data
FOR EACH ROW
DECLARE
BEGIN
IF UPDATING THEN
MERGE INTO ad_integration intg USING dual ON (intg.user_id = :NEW.user_id AND intg.integrated = 'NO')
WHEN MATCHED THEN
UPDATE SET
intg.start_day_of_employment = decode(:NEW.start_day_of_employment, NULL, ' ', :NEW.start_day_of_employment),
intg.end_of_employment = decode(:NEW.end_of_employment, NULL, ' ', :NEW.end_of_employment),
intg.manager_status = :NEW.manager_status,
intg.pid = (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id),
intg.network_access_start_date = (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id)
WHEN NOT MATCHED THEN
INSERT (intg.user_id, intg.start_day_of_employment, intg.end_of_employment, intg.manager_status, intg.pid, intg.network_access_start_date
VALUES (:NEW.user_id, :NEW.start_day_of_employment, :NEW.end_of_employment, :NEW.manager_status, (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id), (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id));
END IF;
END HR_ADINTEGRATION_EMPLOYMENT;
Is it because of using DUAL or something am I missing?
Cheers! :-)
If you want to leave the structure as is and only process the trigger when the specifc fields change, then just do a quick compare (new code lines 7 and 8):
CREATE OR REPLACE TRIGGER INTEGRATION_EMPLOYMENT
AFTER UPDATE OF start_day_of_employment, end_of_employment ON hr_employment_data
FOR EACH ROW
DECLARE
BEGIN
IF UPDATING
AND (:NEW.start_day_of_employment <> :OLD.start_day_of_employment
OR :NEW.end_of_employment <> :OLD.end_of_employment) THEN
MERGE INTO ad_integration intg USING dual ON (intg.user_id = :NEW.user_id AND intg.integrated = 'NO')
WHEN MATCHED THEN
UPDATE SET
intg.start_day_of_employment = decode(:NEW.start_day_of_employment, NULL, ' ', :NEW.start_day_of_employment),
intg.end_of_employment = decode(:NEW.end_of_employment, NULL, ' ', :NEW.end_of_employment),
intg.manager_status = :NEW.manager_status,
intg.pid = (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id),
intg.network_access_start_date = (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id)
WHEN NOT MATCHED THEN
INSERT (intg.user_id, intg.start_day_of_employment, intg.end_of_employment, intg.manager_status, intg.pid, intg.network_access_start_date
VALUES (:NEW.user_id, :NEW.start_day_of_employment, :NEW.end_of_employment, :NEW.manager_status, (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id), (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id));
END IF;
END HR_ADINTEGRATION_EMPLOYMENT;

TSQL - efficient way of setting multiple variables

is their a more efficient way of doing this?
set #ShippingL = (select ShippingL from AuctionProducts where ProductID = #ProductID)
set #ShippingB = (select ShippingB from AuctionProducts where ProductID = #ProductID)
set #ShippingH = (select ShippingH from AuctionProducts where ProductID = #ProductID)
set #ShippingW = (select ShippingW from AuctionProducts where ProductID = #ProductID)
Cheers,
-R
I would think doing one query would be as good as you'll get it:
select
#ShippingL = ShippingL,
#ShippingB = ShippingB,
#ShippingH = ShippingH,
#ShippingW = ShippingW
from
AuctionProducts
where
ProductID = #ProductID
I would imagine this is 4 times faster than the code that you posted. Also, make sure that you have an index defined on the ProductID column of the AuctionProducts table.

Update table with if statement PL/SQL

I am trying to do something like this but am having trouble putting it into oracle coding.
BEGIN
IF ((SELECT complete_date FROM task_table WHERE task_id = 1) IS NULL)
THEN
UPDATE task_table SET complete_date = //somedate WHERE task_id = 1;
ELSE
UPDATE task_table SET complete_date = NULL;
END IF;
END;
But this does not work. I also tried
IF EXISTS(SELECT complete_date FROM task_table WHERE task_id = 1)
with no luck.
I don't think you'd need the procedural block if your actual logic is like the one above.
Assuming this is your task:
"if the value of complete_date for id
1 is NULL, update it with XXX. Otherwise set it to null".
You could just run ...
Update task_table
set complete_date = nvl2(complete_date,NULL, <**your date**>)
where task_id = 1;
This will only update those records where the complete_date is null with your new date.
What is the intention of this part?
IF ((SELECT complete_date FROM task_table WHERE task_id = 1) IS NULL)
Is it to find if there are rows where complete_date is null and task_id = 1?
Or is it to check if there are no rows where task_id = 1?

Resources