Is there a way to use a variable to comment out a line in the where clause? - sql

I have a line in my WHERE clause that would be a nice added feature to be able to toggle. This way the end user doesn't have to run two reports. I haven't found anything like it so I'm thinking you cannot but maybe I am looking at the problem the wrong way and someone else knows a better way.
I have tried to run the code below with the last line as #AND and defining the variable as 'AND' & '--'giving me incorrect syntax error x2.
I also tried IS #NULL and defining the variable as 'NULL' & 'NOT NULL' giving me incorrect syntax error x2
SELECT
item_id
FROM
cba_item_location
WHERE
discontinued='Y'
AND qty_on_hand = '0'
AND (select abc_code from abc_miscdata where abc_code=item_id and abc_type='ITEM' and data_1 ='DISCON_ZERO_SENT') IS NULL
order by item_id
Example 1:
SELECT
item_id
FROM
cba_item_location
WHERE
discontinued='Y'
AND qty_on_hand = '0'
**#AND** (select abc_code from abc_miscdata where abc_code=item_id and abc_type='ITEM' and data_1 ='DISCON_ZERO_SENT') IS NULL
Example 2:
SELECT
item_id
FROM
cba_item_location
WHERE
discontinued='Y'
AND qty_on_hand = '0'
AND (select abc_code from abc_miscdata where abc_code=item_id and abc_type='ITEM' and data_1 ='DISCON_ZERO_SENT') IS **#NULL**
Any ideas?

Option 1: dynamic SQL
Option 2: include a flag into your WHERE clause which will switch it on and off
DECLARE #and bit = 0
IF (some condition) SET #and = 1
...
WHERE
discontinued='Y'
AND qty_on_hand = '0'
AND (#and = 1 AND (select abc_code from abc_miscdata where abc_code=item_id and abc_type='ITEM' and data_1 ='DISCON_ZERO_SENT') IS NULL)

Related

Case expression with Boolean from PostgreSQL to SQL Server

I am translating a query from PostgreSQL to SQL Server. I didn't write the query in PostgreSQL and it's quite complicated for my knowledge so i don't understand every piece of it.
From my understand: we are trying to find the max version from p_policy and when insurancestatus = 7 or 14 / transactiontype = CAN, we compare two dates (whose format are BIG INT).
This is the PG Query:
SELECT *
FROM BLABLABLA
WHERE
pol.vnumber = (
SELECT MAX(pol1.vnumber)
FROM p_policy pol1
AND ( CASE WHEN pol1.insurancestatus IN (7,14)
or pol1.transactiontype IN ('CAN')
-- ('CAN','RCA')
THEN pol1.veffectivedate = pol1.vexpirydate
ELSE pol1.veffectivedate <> pol1.vexpirydate
END
)
AND pol1.vrecordstatus NOT IN (30,254)
etc.
I am used to have a where statement where I compare it to a value. I understand here from the Case statement we will have a boolean, but still that must be compared to something?
Anyway the main purpose is to make it work in SQL, but I believe SQL can't read a CASE statement where THEN is a comparison.
This is what I tried:
SELECT *
FROM BLABLABLA
WHERE pol.vnumber =
(
SELECT MAX(pol1.vnumber)
FROM p_policy pol1
WHERE sbuid = 4019
AND ( CASE WHEN pol1.insurancestatus IN (7,14)
or pol1.transactiontype IN ('CAN')
THEN CASE
WHEN pol1.veffectivedate = pol1.vexpirydate THEN 1
WHEN pol1.veffectivedate <> pol1.vexpirydate THEN 0
END
END
)
AND pol1.vrecordstatus NOT IN (30,254)
etc.
And then I get this error from SQL Server (which directly the last line of the current code - so after the double case statement)
Msg 4145, Level 15, State 1, Line 55
An expression of non-boolean type specified in a context where a condition is expected, near 'AND'.
Thank you !Let me know if it is not clear
I think you want boolean logic. The CASE expression would translate as:
(
(
(pol1.insurancestatus IN (7,14) OR pol1.transactiontype = 'CAN')
AND pol1.veffectivedate = pol1.vexpirydate
) OR (
NOT (pol1.insurancestatus IN (7,14) OR pol1.transactiontype = 'CAN')
AND pol1.veffectivedate <> pol1.vexpirydate
)
)
There are 2 main issues with your snippet, SQL Server-syntax-wise.
SELECT * FROM BLABLABLA WHERE
pol.vnumber = /* PROBLEM 1: we haven't defined pol yet; SQL Server has no idea what pol.vnumber is here, so you're going to get an error when you resolve your boolean issue */
(
SELECT MAX(pol1.vnumber)
FROM p_policy pol1
WHERE sbuid = 4019
AND ( CASE WHEN pol1.insurancestatus IN (7,14)
or pol1.transactiontype IN ('CAN')
THEN CASE
WHEN pol1.veffectivedate = pol1.vexpirydate THEN 1
WHEN pol1.veffectivedate <> pol1.vexpirydate THEN 0
END
END
) /* PROBLEM 2: Your case statement returns a 1 or a 0..
which means your WHERE is saying
WHERE sbuid = 4019
AND (1)
AND pol1.vrecordstatus NOT IN (30,254)
SQL Doesn't like that. I think you meant to add a boolean operation using your 1 or 0 after the parenthesis.
like this: */
= 1
AND pol1.vrecordstatus NOT IN (30,254)

Oracle PLSQL using a dynamic variable in a where clause

For testing in Toad, I have the following code
select ...
from ...
where term_code = :termcode AND
(
case
when :theSubject is not null then SUBJ_CODE = :theSubject
else 1 = 1
end
)
AND ptrm_code <> 8
In short: If theSubject is not entered (is null) I want to display all the courses, otherwise I want to display only those where subject_code is the same as the one entered in the variable window in Toad.
But I get an error:
[Error] Execution (77: 68): ORA-00905: missing keyword
in here:
when :theCourse is not null then sect.SSBSECT_SUBJ_CODE = theCourse
You can use boolean logic:
where
term_code = :termcode
and (:theSubject is null or subj_code = :theSubject)

Unable to Correct Oracle Error ORA-00905 Missing Keyword in SQL

I've been grinding on this small snippet of simple code for a day and can't find the issue causing the error. As the title states, I am getting error ORA-00905 Missing Keyword when trying to execute the following code:
SELECT DISTINCT DM.DESCRIPTION AS "AGENCY",
DM.DEPT_NO AS "DEPT NO",
CASE
WHEN VMP.RESERVE_DT IS NULL THEN
NULL
ELSE
VMP.RESERVE_DT
END AS "RESV_DT",
CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
VMP.EST_PICKUP_DT
END AS "EST_PKUP_DT",
CASE
WHEN VMP.EST_RETURN_DT IS NULL THEN
NULL
ELSE
VMP.EST_RETURN_DT
END AS "EST_RETN_DT",
VMP.EMP_NAME AS "EMPL_NAME",
VMP.UNIT_NO AS "UNIT_NUMBER",
VMP.RENTAL_CLASS_DESCRIPTION AS "RENT_CLS",
VMP.MP_TICKET_NO AS "MP_TKT_NO"
FROM DEPT_MAIN DM
INNER JOIN VIEW_MPOOL VMP ON VMP.DEPT_ID = DM.DEPT_ID
WHERE CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
END
GROUP BY DM.DESCRIPTION,
DM.DEPT_NO,
CASE
WHEN VMP.RESERVE_DT IS NULL THEN
NULL
ELSE
VMP.RESERVE_DT
END,
CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
VMP.EST_PICKUP_DT
END,
CASE
WHEN VMP.EST_RETURN_DT IS NULL THEN
NULL
ELSE
VMP.EST_RETURN_DT
END,
VMP.EMP_NAME,
VMP.UNIT_NO,
VMP.RENTAL_CLASS_DESCRIPTION,
VMP.MP_TICKET_NO
ORDER BY CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
VMP.EST_PICKUP_DT
END ASC
The basis of this code was generated through an adhoc reporting program and was originally fully-qualified. I stripped out the extraneous quotation marks and assigned table aliases to clean it up. Though I hoped these efforts would help me find the issue, I am unable to find the cause. Thank you for your consideration.
Try to replace this :
WHERE
CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN NULL
ELSE TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
END
With :
WHERE
CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN NULL
ELSE TRUNC(VMP.EST_PICKUP_DT)
END
= TRUNC(SYSDATE)
Please note that this whole expression (and others similar in the query) could be simplified as as :
WHERE
TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
When VMP.EST_PICKUP_DT is NULL, TRUNC will return NULL, which will not be equal to TRUNC(SYSDATE).
Here:
WHERE
CASE
WHEN VMP.EST_PICKUP_DT IS NULL
THEN NULL
ELSE TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
END
The END is after a comparison and the case is not being compared against a value.
Switch it like:
WHERE
CASE
WHEN VMP.EST_PICKUP_DT IS NULL
THEN NULL
ELSE TRUNC(VMP.EST_PICKUP_DT)
END = TRUNC(SYSDATE)
Which as horse says, can just be simplified as
WHERE TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
since a NULL value on VMP.EST_PICKUP_DT will never match TRUNC(SYSDATE).
can't find the issue causing the error
Although I suppose that #EzLo and #a_horse_with_no_name maybe already found error in this case, I can propose a general procedure in debugging such queries.
Step 1: Debug your JOIN- and WHERE- predicates
Comment everything in your SELECT-statement, leave only JOINs, substitute fields with * or constant expression.
E.g.
SELECT 1
-- DISTINCT DM.DESCRIPTION AS "AGENCY",
-- DM.DEPT_NO AS "DEPT NO",
-- CASE
-- ....
-- VMP.RENTAL_CLASS_DESCRIPTION AS "RENT_CLS",
-- VMP.MP_TICKET_NO AS "MP_TKT_NO"
FROM DEPT_MAIN DM
INNER JOIN VIEW_MPOOL VMP ON VMP.DEPT_ID = DM.DEPT_ID
WHERE CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
END
-- GROUP BY DM.DESCRIPTION,
-- ....
-- ORDER BY ..
In case of multiple complex predicates - uncomment one predicate at a time.
Step 2: Debug your GROUP BYs and HAVINGs
Uncomment GROUP BY section and edit fields section of your query.
If you have complex groupby's - uncomment by one field at time.
Start from simplest to complex
SELECT
DM.DESCRIPTION
,DM.DEPT_NO
-- ...
FROM DEPT_MAIN DM
INNER JOIN VIEW_MPOOL VMP ON VMP.DEPT_ID = DM.DEPT_ID
WHERE CASE
WHEN VMP.EST_PICKUP_DT IS NULL THEN
NULL
ELSE
TRUNC(VMP.EST_PICKUP_DT) = TRUNC(SYSDATE)
END
GROUP BY DM.DESCRIPTION
,DM.DEPT_NO
Copy-paste your GROUP BYs into SELECT fields section.
Step 3: Debug you aggregates, field transformation and renames
Now you have correct SELECT-query but probably not in the shape you want.
Step 4: Debug ORDER BYs
You have correct shape and in last step you need to ORDER BY your data.
If you have decent editor/IDE you can find source of error in 5-10 minutes even in cases of complex queries (and even RDBMS engine bugs)
P.S.
It's better to note which version of RDBMS you are using.

SQL Update when not null

I'm trying to set a column in the fabcon table only if the original column is null.
This is the code I've already tried.
UPDATE dbo.fabcon
SET ext = COALESCE(ext, ( SELECT CASE WHEN [<3] IS NOT NULL THEN '3' END AS extent
FROM dbo.spreadsheetData ))
This is the error I'm getting:
Sub-query returned more than 1 value. This is not permitted when the sub-query follows =, !=, <, <= , >, >= or when the sub-query is used as an expression.
Can anyone see where I've gone wrong?
Thanks. :)
EDIT: the two tables fabcon and spreadsheetData are linked by a column called main1
EDIT2: I've updated the query to this:
UPDATE dbo.fabcon
SET ext = (SELECT CASE WHEN [<3] IS NOT NULL THEN '3' END
FROM dbo.spreadsheetData ssd
WHERE ssd.id = fabcon.id
)
WHERE ext IS NULL;
However, its still failing with the same error.
You need a link between the table fabcon and spreadsheetData. Assuming it is called id:
UPDATE dbo.fabcon
SET ext = (SELECT CASE WHEN [<3] IS NOT NULL THEN '3' END)
FROM dbo.spreadsheetData ssd
WHERE ssd.id = fabcon.id
)
WHERE ext IS NULL;
Note that I removed the coalesce() and replaced it with a where clause for the update. This prevents the query from updating rows unnecessarily (with unchanged values).
DECLARE #PAth INT
Select #path = COALESCE(ext,'')+[<3]+';' FROM dbo.spreadsheetData
UPDATE dbo.fabcon
SET ext = CASE WHEN #PAth IS NOT NULL
THEN '3' ELSE ''
END AS Extent
FROM dbo.fabcon f WHERE f.id = #path
may be this works i think
This should work for you. Assuming I have understood your original query correctly
UPDATE dbo.fabcon
SET
ext = ssd.[column to insert data from]
FROM
dbo.spreadsheetData ssd
WHERE
ext IS NULL
AND
fabcon.id = ssd.id
This assumes the id in the ssd table is the id from the fabcon table. Otherwise just change the id matching based on your column specification
UPDATE dbo.fabcon
SET ext = (SELECT TOP 1 CASE WHEN [<3] IS NOT NULL THEN '3' END
FROM dbo.spreadsheetData ssd
WHERE ssd.main1 = fabcon.main1
ORDER BY 1
)
WHERE ext IS NULL;
with the 2 tables related via "main1" (as now indicated) and an arbitrary "TOP 1" thrown in to avoid the error, this might work.
but: the best way to get an answer is to provide some sample data and an expected result

Select Logic in Query. Is this possible in Oracle?

Im trying to implement some sort of logic on the select statement of the query. I want it so that if no attribute is given, or if the inAttribute is 'NONE'; it will return the date and ALL of the values (compprice, compspread,price,spread,run).
If a value was given to in attribute then i want it to return the value it requested for (Refer to the case statement i tried to do).
Below is my attempt at it, and it is just not working. Any help please?
SELECT
mi.date,
IF inAttribute = '' THEN
mi.compprice,
mi.compspread,
mi.price,
mi.spread,
mi.run
ELSE
CASE inAttribute
WHEN 'CP' THEN mi.compprice,
WHEN 'CS THEN mi.compspread,
WHEN 'MP' THEN mi.price,
WHEN 'MS' THEN mi.spread,
WHEN 'R' THEN mi.run
END
END IF
FROM userValueTable mi
WHERE mi.index_family = inIdxFamily
AND mi.index_id = inIdxId
AND mi.date_>= inStartDate
AND mi.date_<= inEndDate
ORDER by mi.date_ ASC;
Few remarks You can't have variable column list from one line to another. '' is equal to NULL, comparing NULL with equality ( = ) is always false. you can have some fixed number of columns and set value of any column using CASE clause.
Oracle doesn't have an IF for SQL. Use CASE instead - it can act like a C/C#/Java/etc switch - case as you have it in your query, and it can also act like an if.
Also, as mentioned above:
You're stuck with returning a constant number of columns unless you use dynamic SQL
In Oracle, '' is treated as NULL so instead of = '' use IS NULL.
If you don't want to go to Dynamic SQL, you could add a "type" column to your select list and then null out any inapplicable values. Your downstream logic could pick the values to use (or ignore) based on the type. Here's an example:
SELECT
mi.date,
CASE
WHEN inAttribute IS NULL THEN 'inAttrNull'
ELSE 'inAttrNotNull'
END AS RecordType,
CASE WHEN inAttribute IS NULL THEN mi.compprice END AS compprice,
CASE WHEN inAttribute IS NULL THEN mi.compspread END AS compspread,
CASE WHEN inAttribute IS NULL THEN mi.price END AS price,
CASE WHEN inAttribute IS NULL THEN mi.spread END AS spread,
CASE WHEN inAttribute IS NULL THEN mi.run END AS run,
CASE inAttribute
WHEN 'CP' THEN mi.compprice
WHEN 'CS' THEN mi.compspread
WHEN 'MP' THEN mi.price
WHEN 'MS' THEN mi.spread
WHEN 'R' THEN mi.run
END AS SpecialValue
FROM userValueTable mi
... and your WHERE and ORDER BY clauses
You'll get a result set something like this:
RecordType compprice compspread price spread run specialvalue
------------- ---------- ---------- ---------- ---------- ---------- ------------
inAttrNotNull (null) (null) (null) (null) (null) 1234.56
inAttrNull 111.11 222.22 333.33 444.44 555.55 (null)
I know this isn't what you wanted, but it may be something you can work with as an alternative.
There is no IF in Oracle SQL, only in PL/SQL. You have to rewrite it to CASE. The same as you did in your query in ELSE part (you missed a single closing quote after 'CS' THEN...).
SELECT ...
(CASE WHEN inAttribute IS NULL THEN mi.compprice
WHEN .... THEN...
WHEN .... THEN...
...
ELSE ...
END) AS some_column_alias
FROM ...