If Else logic converting to Select case - Oracle - oracle

IF inputVariable = '0'
THEN
DELETE existingTemptable
WHERE status != 999;
ELSE
IF inputVariable = '1'
THEN
DELETE existingTemptable
WHERE status = 999;
ELSE
DELETE existingTemptable
WHERE status != 999
AND date < utils.dateadd('MONTH', -6, SYSTIMESTAMP);
END IF;
END IF;
This If logic is present on a temp table and I have to remove the temp table and make it only select query , so approached with WITH CTE but stuck in the below
what should be in the where clause
with existingTemptable as
(
//got the temp table here
), myTable as
(
Select * from existingTemptable
**where
status = CASE WHEN inputVariable = '0' THEN 999
WHEN inputVariable != '0' AND inputVariable != '1' THEN 999
ELSE status
END**
)Select * from myTable
What to put in WHERE clause so that it mimics the If logic above

You have to be careful if inputVariable or status (or both) may be null. The rest is a direct application of logical rules one learns (or should learn) in middle school.
select *
from existingTemptable
where inputVariable = '0' and (status = 999 or status is null)
or
inputVariable = '1' and (status != 999 or status is null)
or
(inputVariable is null or inputVariable not in ('0', '1'))
and (status = 999 or status is null) and date >= [whatever]
Note - even in the absence of null handling, you can't write the where clause with a case expression; that's because in one branch you require "not equal", and you can't do it with a simple case expression.

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

ORA-00920: Invalid relational operator (no missing/extra parenthesis)

I have an error when I try to execute the following query and I don't understand why.
SELECT DISTINCT lpad(obj.no, 4, '0') || ' - ' || obj.nom, obj.no
FROM TABLE(objects_pkg.get_all()) obj
WHERE obj.start_date <=
(CASE
WHEN util_pkg.is_date_valid(p_date => :v_start_date) ̲T̲H̲E̲N
to_date(:v_start_date, 'YYYY-MM-DD')
ELSE
trunc(SYSDATE)
END)
I checked for missing / extra parenthesis but I couldn't find any.
I tried several ways of structuring the CASE like the following but none of them worked.
SELECT DISTINCT lpad(obj.no, 4, '0') || ' - ' || obj.nom, obj.no
FROM TABLE(objects_pkg.get_all()) obj
WHERE (CASE
WHEN util_pkg.is_date_valid(p_date => :v_start_date) ̲T̲H̲E̲N
CASE WHEN obj.start_date <= to_date(:v_start_date, 'YYYY-MM-DD') THEN 1 ELSE 0 END
ELSE
CASE WHEN obj.start_date <= trunc(SYSDATE) THEN 1 ELSE 0 END
END) = 1
The error is always the same and is always triggered on the first T̲H̲E̲N̲ keyword of the first WHEN. I tried with and without the parenthesis, I tried to remove the THEN keyword and I tried a lot of things but nothing worked. The error is: ORA-00920: Invalid relational operator
I've also tried to change the entire where clause to the following but it didn't help.
SELECT DISTINCT lpad(obj.no, 4, '0') || ' - ' || obj.nom, obj.no
FROM TABLE(objects_pkg.get_all()) obj
WHERE (
(
TRIM(:v_start_date) ̲I̲S NULL
AND util_pkg.is_date_valid(p_date => :v_start_date)
AND obj.start_date <= to_date(:v_start_date, 'YYYY-MM-DD')
)
OR
(
(
:v_start_date IS NULL
OR NOT util_pkg.is_date_valid(p_date => :v_start_date)
)
AND obj.start_date <= trunc(SYSDATE)
)
)
For the above query, the error is triggered on the first I̲S̲ keyword within the WHERE clause (TRIM(:v_start_date) I̲S̲ NULL) but the error is still an ORA-00920.
Note: util_pkg.is_date_valid returns a BOOLEAN
I think your issue is that you are not testing the value from util_pkg.is_date_valid.
The WHEN part of the CASE statement needs to be tested against something.
CASE
WHEN util_pkg.is_date_valid(p_date => :v_start_date) >= ? ̲T̲H̲E̲N ...

Oracle case statement not working

I want to use case statement for a column like below
SELECT sr_no, TYPE, stage, party_name, amount, remarks, exp_type, exp_id,
voucher_no, cheque_no, cheque_dt, chq_favr_name, attachment,
CASE NVL (amount, 0) = 0 THEN checkVal = 0
ELSE
checkVal = 1
FROM xxcus.xxacl_pn_expense_info
WHERE mkey = '354'
AND ((NVL (amount, 0) <> 0) OR (party_name IS NOT NULL))
ORDER BY sr_no
But I am getting error as
ORA-00923: FROM keyword not found where expected
SELECT sr_no, TYPE, stage, party_name, amount, remarks, exp_type, exp_id,
voucher_no, cheque_no, cheque_dt, chq_favr_name, attachment,
CASE WHEN NVL(amount, 0) = 0 THEN 0 ELSE 1 END AS checkVal
FROM xxcus.xxacl_pn_expense_info
WHERE mkey = '354'
AND ((NVL (amount, 0) <> 0) OR (party_name IS NOT NULL))
ORDER BY sr_no
you're missing an END
SELECT sr_no, TYPE, stage, party_name, amount, remarks, exp_type, exp_id,
voucher_no, cheque_no, cheque_dt, chq_favr_name, attachment,
CASE WHEN NVL (amount, 0) = 0 THEN checkVal = 0
ELSE
checkVal = 1
END
FROM xxcus.xxacl_pn_expense_info
WHERE mkey = '354'
AND ((NVL (amount, 0) <> 0) OR (party_name IS NOT NULL))
ORDER BY sr_no

Multiple Update statements running slow in SQL Stored procedure

Please refer to the below SQL commands which is a part of the stored procedure. The stored procedure creates a temporary table named #TREPORT and then I perform following multiple updates on SODATE column.
The temporary table (#TREPORT) has about 1 million records and below statements are making performance slower. How can I improve it further?
#SDATE and #EDATE are parameters which is starting date and ending date.
Thanks in advance.
UPDATE #TREPORT SET
SODATE = '1900-01-01 00:00:00.000' where #TREPORT.SODATE is NULL
UPDATE #TREPORT SET
SODATE = (SELECT TOP 1 docdate from SO200
where SO200.NUMBORIG = #TREPORT.SOPNr
AND SO200.SOTYPE = '3'
-- AND
--DOCDATE is not null and DOCDATE >= '' +CONVERT(varchar(10),#SDATE,101) +''
-- and DOCDATE <= '' +CONVERT(varchar(10),#EDATE,101) +''
)
where #TREPORT.SODATE = '1900-01-01 00:00:00.000' or #TREPORT.SODATE is NULL
UPDATE #TREPORT SET
SODATE = (SELECT TOP 1 docdate from SO100
where SO100.NUMBORIG = #TREPORT.SOPNr
AND SO100.SOTYPE = '3'
-- AND
--DOCDATE is not null and DOCDATE >= '' +CONVERT(varchar(10),#SDATE,101) +''
-- and DOCDATE is not null and DOCDATE <= '' +CONVERT(varchar(10),#EDATE,101) +''
)
where #TREPORT.SODATE = '1900-01-01 00:00:00.000' or #TREPORT.SODATE is NULL
UPDATE #TREPORT SET
RowValue = 'C' where
(#TREPORT.SODATE < '' +CONVERT(varchar(10),#SDATE,101) +''
or #TREPORT.SODATE > '' +CONVERT(varchar(10),#EDATE,101) +'')
UPDATE #TREPORT SET
RowValue = 'D' where #TREPORT.SODATE = '1900-01-01 00:00:00.000'
or #TREPORT.SODATE is NULL
Large updates are best performed in batches. See the solution here:
http://www.sqlusa.com/bestpractices/largeupdate/
As for combining your updates, your first update is completely superfluous because you're replacing NULL with a default value, and the other updates replace "NULL or {the default value}", so you could have just skipped the first one completely.
The other 4 updates could be combined into one with a CASE statement.
UPDATE #TREPORT SET SODATE=CASE
WHEN EXISTS(SELECT * from SO200 where SO200.NUMBORIG = #TREPORT.SOPNr AND SO200.SOTYPE = '3')
THEN (SELECT TOP 1 docdate from SO200
where SO200.NUMBORIG = #TREPORT.SOPNr
AND SO200.SOTYPE = '3')
WHEN EXISTS(SELECT * from SO100 where SO100.NUMBORIG = #TREPORT.SOPNr AND SO100.SOTYPE = '3')
THEN (SELECT TOP 1 docdate from SO100
where SO100.NUMBORIG = #TREPORT.SOPNr
AND SO100.SOTYPE = '3')
ELSE '1900-01-01 00:00:00.000'
END
, RowValue=CASE
WHEN (#TREPORT.SODATE < '' +CONVERT(varchar(10),#SDATE,101) +''
or #TREPORT.SODATE > '' +CONVERT(varchar(10),#EDATE,101) +'')
THEN 'C'
ELSE 'D'
END
where #TREPORT.SODATE = '1900-01-01 00:00:00.000' or #TREPORT.SODATE is NULL

LINQ: A query body must end with a select clause or a group clause and other errors

I have the following SQL statement:
CASE
WHEN wt.pmtlr_oi IS NULL OR (SELECT COUNT(*) FROM mc.SCHEDENTRY WITH (NOLOCK) WHERE wt_oi = wt.wtskoi AND shedref_oi NOT IN (SELECT shdoi FROM mc.SCHDULE WITH (NOLOCK) WHERE aenm LIKE '%Breakin%')) = 0 AND wt.pmtlr_oi IS NULL
THEN 'Break-In'
ELSE 'Planned'
END AS schedule
which I have translated into:
Schedule = wt.pmtlr_oi == null || (from sch in SCHEDENTRies where wt_oi == wt.wtskoi && shedref_oi !(from sc in SCHDULEs
where sc.Aenm.Contains("Breakin") select sc.Shdoi)).Count() == 0 && wt.pmtlr_oi == null ? "Break-In" : "Planned"}
Here's how it looks in the select statement:
select new {Schedule = wt.pmtlr_oi == null || (from sch in SCHEDENTRies where wt_oi == wt.wtskoi && shedref_oi !(from sc in SCHDULEs
where sc.Aenm.Contains("Breakin") select sc.Shdoi)).Count() == 0 && wt.pmtlr_oi == null ? "Break-In" : "Planned"});
However when I try and run it there are some problems which I do not know how to fix. The first one is that the compiler doesn't appear to like the NOT IN found here:
&& shedref_oi !(from sc in SCHDULEs
I get a "A query body must end with a select clause or a group clause" error.
The compiler also doesn't like this:
select sc.Shdoi)).Count() == 0
On the outer parenthesis I get a "Syntax error ',' expected" error and on the period I get a "Statement expected" error message.
I would appreciate some help in troubleshooting this.
EDIT:
OK, After the comments I have corrected the LINQ statement to look like this:
select new {Schedule = wt.pmtlr_oi == null || (from sch in SCHEDENTRies where wt_oi == wt.wtskoi && !(from sc in SCHDULEs
where sc.Aenm.Contains("Breakin") select sc.Shdoi).Contains(shedref_oi)).Count() == 0 && wt.pmtlr_oi == null ? "Break-In" : "Planned"});
and the compiler likes it. However, it still doesn't like the .Count(). I get a "Statement expected" error. Am I incorrect in using .Count() for the sql SELECT COUNT(*)?

Resources