How to improve the performance of the SQL query? - oracle

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

Related

Oracle: Value from main query is not available in subquery

I have this query, and one of its column is a subquery that should be bringing a list of values using a listagg function. This list has its starting point as the S.ID_ORGAO_INTELIGENCIA value. The list is a should be, it always has values.
The listagg function is consuming an inline view that uses a window function to create the list.
select *
from (
SELECT DISTINCT S.ID_SOLICITACAO,
S.NR_PROTOCOLO_SOLICITACAO,
S.DH_INCLUSAO,
S.ID_USUARIO,
U.NR_CPF,
OI.ID_MODULO,
OI.ID_ORGAO_INTELIGENCIA,
OI.NO_ORGAO_INTELIGENCIA,
R.ID_ATRIBUICAO,
P.ID_PERMISSAO,
1 AS TIPO_NOTIFICACAO,
(
select LISTAGG(oc6.ID_ORGAO_INTELIGENCIA || '-' || oc6.ord || '-', '; ') WITHIN GROUP (ORDER BY oc6.ord) eai
from (
SELECT oc1.ID_ORGAO_INTELIGENCIA,
oc1.ID_ORGAO_INTELIGENCIA_PAI,
oc1.SG_ORGAO_INTELIGENCIA,
rownum as ord
FROM TB_ORGAO_INTERNO oc1
WHERE oc1.DH_EXCLUSAO is null
-- THE VALUE FROM S.ID_ORGAO_INTELIGENCIA IS NOT AVAILBLE HERE
START WITH oc1.ID_ORGAO_INTELIGENCIA = S.ID_ORGAO_INTELIGENCIA
CONNECT BY prior oc1.ID_ORGAO_INTELIGENCIA_PAI = oc1.ID_ORGAO_INTELIGENCIA
) oc6) aproPrec
FROM TB_SOLICITACAO S
INNER JOIN TB_ORGAO_INTERNO OI ON S.ID_ORGAO_INTELIGENCIA = OI.ID_ORGAO_INTELIGENCIA
INNER JOIN TB_RELACIONAMENTO_ATRIBUICAO R
ON (R.ID_MODULO = OI.ID_MODULO AND R.ID_ORGAO_INTELIGENCIA IS NULL AND
R.ID_SOLICITACAO IS NULL)
INNER JOIN TB_PERMISSAO P
ON (P.ID_USUARIO = :usuario AND P.ID_ORGAO_INTELIGENCIA = :orgao AND
P.ID_ATRIBUICAO = R.ID_ATRIBUICAO)
INNER JOIN TB_USUARIO U ON (U.ID_USUARIO = S.ID_USUARIO)
WHERE 1 = 1
AND U.DH_EXCLUSAO IS NULL
AND P.DH_EXCLUSAO IS NULL
AND S.DH_EXCLUSAO IS NULL
AND OI.DH_EXCLUSAO IS NULL
AND R.ID_ATRIBUICAO IN :atribuicoes
AND P.ID_STATUS_PERMISSAO = 7
AND OI.ID_MODULO = 1
AND S.ID_STATUS_SOLICITACAO IN (1, 2, 5, 6)
and s.ID_ORGAO_INTELIGENCIA in (SELECT DISTINCT o.ID_ORGAO_INTELIGENCIA
FROM TB_ORGAO_INTERNO o
WHERE o.DH_EXCLUSAO IS NULL
START WITH o.ID_ORGAO_INTELIGENCIA = 3
CONNECT BY PRIOR o.ID_ORGAO_INTELIGENCIA = o.ID_ORGAO_INTELIGENCIA_PAI)
);
The problem is that the aproPrec column is always returning null as its result.
If I force the criteria to have the S.ID_ORGAO_INTELIGENCIA hardcoded, the list returns its true value.
If I chance this:
START WITH oc1.ID_ORGAO_INTELIGENCIA = S.ID_ORGAO_INTELIGENCIA
To this:
START WITH oc1.ID_ORGAO_INTELIGENCIA = 311
where 311 is the value that the S.ID_ORGAO_INTELIGENCIA column really has.
Is there a way to make this query works as 'I think' it should work?
To make it work, I changed the subquery by this another one:
(
select qt_.*
from (
SELECT QRY_NAME.*,
rownum as ord
FROM (
SELECT oc1.ID_ORGAO_INTELIGENCIA,
oc1.ID_ORGAO_INTELIGENCIA_PAI,
connect_by_root (oc1.ID_ORGAO_INTELIGENCIA) as root
FROM TB_ORGAO_INTERNO oc1
CONNECT BY NOCYCLE PRIOR oc1.ID_ORGAO_INTELIGENCIA_PAI = oc1.ID_ORGAO_INTELIGENCIA
) QRY_NAME
WHERE root = s.ID_ORGAO_INTELIGENCIA
) qt_
)

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
);

Column ambiguously defined Oracle SQL

I'm facing this ambiguously defined error. I understand this is due to alias not defined properly but I am not able to understand in the below query why this error is coming. I'm using Oracle.
SELECT
papf.person_number as personnumber,
paam.position_id as position,
fabu.bu_name
FROM
(SELECT
papf.person_number,
paam.person_id,
fabu.bu_name,
fabu.bu_id,
paam.assignment_id,
paam.assignment_number,
paam.action_code,
paam.effective_start_date,
wft.outcome,
htd.state,
htd.status,
Count(paam.assignment_id)
over (
PARTITION BY paam.assignment_id) rowcnt
FROM
per_all_assignments_m paam,
per_all_people_f papf,
hrc_txn_header hth,
hrc_arm_process_vl hapv,
hrc_txn_data htd,
fa_fusion_soainfra.wftask wft,
fun_all_business_units_v fabu
WHERE
paam.primary_assignment_flag = 'Y'
AND paam.effective_latest_change = 'Y'
AND paam.assignment_status_type = 'ACTIVE'
AND paam.action_code IN ( 'GLB_TRANSFER', 'TRANSFER' )
AND hth.subject = 'PER_ALL_PEOPLE_F'
AND hth.subject_id = paam.person_id
AND hth.object IN ( 'PER_ALL_ASSIGNMENTS_M', 'PER_ALL_PEOPLE_F' )
AND hth.object_id = Decode(hth.object, 'PER_ALL_ASSIGNMENTS_M', paam.assignment_id,
'PER_ALL_PEOPLE_F', paam.person_id)
AND hapv.process_id = hth.process_id
AND hapv.txn_module_identifier IN ( 'Transfers', 'ManageEmployment', 'AddWorkRelationship' )
AND htd.transaction_id = hth.transaction_id
AND wft.identificationkey = To_char(hth.transaction_id)
AND SYSDATE BETWEEN papf.effective_start_date AND papf.effective_end_date
AND paam.person_id = papf.person_id
and sysdate between fabu.date_from and fabu.date_to
and fabu.status='A'
and paam.business_unit_id=fabu.bu_id
GROUP BY papf.person_number,
paam.person_id,
paam.assignment_id,
fabu.bu_name,
fabu.bu_id,
paam.assignment_number,
paam.action_code,
paam.effective_start_date,
wft.outcome,
htd.state,
htd.status) t1,
per_all_people_f papf,
per_all_assignments_m paam,
fun_all_business_units_v fabu
WHERE rowcnt = 1
AND outcome = 'APPROVE'
AND state = 'COMPLETE'
AND status = 'APPROVED'
AND paam.person_id = t1.person_id
AND paam.action_code = t1.action_code
AND paam.assignment_status_type = 'INACTIVE'
AND paam.assignment_sequence = 1
AND paam.effective_start_date = t1.effective_start_date
AND paam.assignment_type = 'E'
and papf.person_id = t1.person_id
AND papf.effective_start_date = t1.effective_start_date
AND fabu.bu_id = t1.bu_id
I'm defining the paam table and papf table the same way and not facing issue in them.
Why I am facing this error when I try to add fabu table in end ?
You forgot to add t1. when refer to some columns that can be found in other tables:
WHERE t1.rowcnt = 1
AND t1.outcome = 'APPROVE'
AND t1.state = 'COMPLETE'
AND t1.status = 'APPROVED'

Oracle Update statement with if conditions

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
)

What is the right Update Statement in Oracle 11g

My original update statement is still working great in Sybase (see below) but we're migrating to Oracle 11g and I have to convert this update statement into Oracle Update.
I tried so many version and keep getting error, I guess I have not gotten a grib of how Oracle Update statement works. Can anyone help?
My original good Update Statement (in Sybase):
UPDATE Valid
SET A.status = 'X',
A.reason = 'Missing'
FROM Valid A, Valid B
WHERE A.id_number = B.id_number
AND A.session_id = 69
AND A.userid = 'BS'
AND A.status = 'A'
AND isnull(B.street1, ' ') = ' '
Below is my Oracle version that is not working no matter what I did:
MERGE
INTO um_valid Target
USING (select * from um_valid) SOURCE
ON (t1.id_number = t2.id_number)
WHEN MATCHED THEN
UPDATE
SET status = 'X',
reason = 'Missing (street 1)'
WHERE Target.session_id = 69
AND Target.userid = 'BS'
AND Target.status = 'A'
AND NVL(SOURCE.street1, ' ') = ' ')
The error I'm getting:
ORA-00933: SQL command not properly ended
The WHERE clause at the end isn't appropriate. Maybe you need this:
MERGE
INTO um_valid Target
USING (
select distinct id_number
from um_valid
where street1 is null
) SOURCE
ON (
Target.id_number = SOURCE.id_number
AND Target.session_id = 69
AND Target.userid = 'BS'
AND Target.status = 'A'
)
WHEN MATCHED THEN UPDATE SET
status = 'X',
reason = 'Missing (street 1)'
You can use a normal update statement. Merge is for bulk operations.
If you need to update something when it exists or insert when it doesn't then you can use a merge statement.
So for your example try using the following:
UPDATE Valid
SET status = 'X',
reason = 'Missing'
WHERE session_id = 69
AND userid = 'BS'
AND status = 'A'
AND street1 is null
The above statement will update all rows in table "Valid" where session_id equals 69, userid equals BS, status equals A and street1 is empty (null).
I think this is what you need, if this is not the case pls let me know why you join valid with valid. The I will adjust my update.
This ought to do it:
UPDATE Valid a
SET status = 'X',
reason = 'Missing'
WHERE A.session_id = 69
AND A.userid = 'BS'
AND A.status = 'A'
AND exists (select null
from valid b
where a.id_number = b.id_number
AND coalesce(B.street1, ' ') = ' ')

Resources