I have a nested DECODE statement that I am trying to rewrite from Oracle to SQL Server and it is giving me fits. Can anyone please help me to rewrite this line:
DECODE(UR.UR_REG_IND, 'P', 'P', 'Y') = DECODE(:UR_REG_IND, 'B', DECODE(UR.UR_REG_IND, 'P', 'P', 'Y'), :UR_REG_IND)
I understand the :UR_REG_IND is an input variable #UR_REG_IND and I also understand the DECODE is a type of CASE in SQL, but I am having all kinds of trouble trying to rewrite this without a nested CASE statement, if its even possible.
Something along these lines. The parentheses are not needed but they may help readability.
case ur.ur_reg_ind when 'P' then 'P' else 'Y' end =
case :ur_reg_ind when 'B' then (case ur.ur.reg_ind when 'P' then 'P' else 'Y' end)
else :ur_reg_ind end
Note that this translation should work equally well in Oracle itself - it is actually how I would write that condition. It is longer, perhaps, but to me it seems much easier to read and understand (and therefore to maintain).
Related
This question already has answers here:
SQL Server : check if variable is Empty or NULL for WHERE clause
(6 answers)
Closed 6 months ago.
I'm not sure if CASE is what I actually need to use here, but basically what I am trying to do is apply "WHERE ba.batchid = #batchId" but only if #batchId is not null.
Basically something like this, but this gives an error around the ba.batchid = '2' area ('2' is what the #batchId would come out to).
CASE WHEN '2' != '' THEN ba.batchid = '2' ELSE null END
It helps to think of Case statements as a scalar value. The problem you are experiencing is caused by doing a comparison within the case statement. Basically, you need to pull the comparison out of the case statement.
I'm not sure of the logic you are trying to use, but the following syntax should be correct.
CASE WHEN '2' != '' THEN ba.batchid ELSE null END = '2'
Note that the = '2' is moved to the end. This way, the case statement will return batchid or null depending on the WHEN statement. This value is then compared to '2'.
Try this:
WHERE NULLIF(#batchId, '') IS NOT NULL AND ba.batchid = #batchid
First condition avoids empty('') as well as NULL with #batchid. Second will match the table value.
Take it out of the SELECT part of your statement entirely and put it in the WHERE clause (after FROM)
WHERE ba.batchid = #batchId
AND ba.batchid IS NOT NULL
Note that the AND ba.batchid IS NOT NULL is not necessary here as the first line will filter any nulls. However there are versions of SQL where this is not the case and retaining it in the query still works, hence I have left it in.
I am trying to check a column which belongs to View "IS NULL" and it works good with select statement:
SELECT TOP (1000) [Invoice_Number]
,[Invoice_Date]
,[Invoice_Amount]
,[Invoice_CoCd]
,[Invoice_vendor]
,[Invoice_PBK]
,[Invoice_DType]
,[Invoice_DueDate]
,[Invoice_ClgDate] FROM [dbo].[viewABC] where Invoice_PBK IS NULL
Now I have an update statement, where I need to update a column in a table based on NULL in VIEW:
UPDATE cis
SET
cis.InvoiceStatus =
(
CASE
WHEN RTRIM(LTRIM(imd.[Invoice_PBK])) IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD'
THEN '233' END)
FROM
[dbo.[tblABC] cis,
[dbo].[viewABC] imd
WHERE [condition logic]
These is no issue with where condition, the IS NULL in the CASE expression causing the problem.
Can someone help please?
You may want to just test your Logic piece by piece.
Try
SELECT ISNULL(RTRIM(LTRIM(imd.[Invoice_PBK])),'Hey Im Null')
FROM
[dbo].[tblABC] cis,
[dbo].[viewABC] imd
WHERE [condition logic]
See if you get that String value on your returned column(s) from the Query. Then, build from there. It could be something as simple as the JOIN. Which I'm not a fan of that old syntax but, without more info on this table other than [conditions]. It's hard to just guess an answer for you. You have no detailed evidence that helps us. It very well could be your conditions but, you're saying "condition logic" and that does nothing for the group on this thread.
Looking at this expression:
cis.InvoiceStatus =
CASE
WHEN RTRIM(LTRIM(imd.[Invoice_PBK])) IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD' THEN
'233'
END
And this symptom:
CIS.InvoiceStatus gets updated with NULL
The obvious conclusion is neither WHEN condition is met, and therefore the result of the CASE expression is NULL.
Maybe you wanted this, which will preserve the original value in that situation:
cis.InvoiceStatus =
CASE
WHEN RTRIM(LTRIM(imd.[Invoice_PBK])) IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD' THEN
'233'
ELSE
cis.InvoiceStatus
END
Or maybe you wanted this, to also match an empty string value:
cis.InvoiceStatus =
CASE
WHEN NULLIF(RTRIM(LTRIM(imd.[Invoice_PBK])),'') IS NULL THEN
'HELLO'
WHEN RTRIM(LTRIM(imd.Invoice_DType)) = 'RD' THEN
'233'
END
It's also worth pointing out the two WHEN conditions are looking at two different columns.
Finally, it may be worth a data clean-up project here. Needing to do an LTRIM() will break any chance of using indexes on those fields (RTRIM() is slightly less bad), and index use cuts to the core of database performance.
Im sorry I do not have a complete query because my original is actually very long but I feel you may be able to spot where I have an error in my syntax. Basically I declare 2 variables and if one variable is blank I need the where statement to be where the field is not in the other variable.
Where dnCP_FromServiceDate >= '01/01/2016' And
dnCP_FromServiceDate <= '01/31/2016' And
dnCP_RecordStatus <> 'V'
AND CASE WHEN #inpDXIN = '' THEN
predxDiagnosisCode not in (#inpDXNOTIN)
ELSE predxDiagnosisCode IN (#inpDXIN)
END
Even if I could get a snippet of a query using a similar statement i can figure mine out but i cant find anything similar. Any help is greatly appreciated
In general, you don't want to use case in a where clause. Instead, just use regular boolean logic:
Where dnCP_FromServiceDate >= '2016-01-01' and
dnCP_FromServiceDate <= '2016-01-31' and
dnCP_RecordStatus <> 'V' and
( (#inpDXIN = '' and predxDiagnosisCode <> #inpDXNOTIN) or
(#inpDXIN <> '' and predxDiagnosisCode IN (#inpDXIN)
)
Notes:
Use ISO/ANSI standard date formats. Much less ambiguous.
IN (#var) is the same as = #var. You cannot pass an in list through a variable. If you need that functionality, then ask another question.
Most dialects of SQL do not allow boolean expressions to be returned from a case. The above gets around this "limitation".
I have a long stored procedure with cross joins and left joins. I have several parameters in this table. On the last two left joins, I want to add a conditional where clause based on a parameter.
I will call this parameter #NonCAT which basically category code. The where clause that I am trying to implement just weeds out the non-category codes. The codes for the non-category codes are as follows:
CATCOD IN ('0', '114', '214', '314', '414', '614')
So any of those numbers in the CATCOD column are considered noncat codes.
Otherwise, if they are included, like if they are not in a where clause, they are considered cat codes. so here is my where clause in the last two left joins:
AND CASE
WHEN il.CATCOD IN ('0', '114', '214', '314', '414', '614')
THEN 'NonCAT'
ELSE 'CAT'
END = #NonCAT
This works just fine if I am trying to extract the category codes the #NonCAT variable is just a varchar(20) and it's set to 'NonCAT' as its value for now for the sake of testing. With the where clause in place, I am going to extract the non-cat codes.
I want a conditional statement, say if the variable #NonCAT = 'CAT', I want to omit that where clause. How do I go about doing this? I have tried various case statements and it's harder than it sounds. Thanks so much for the help.
Edit: I tried using iff statement in a where clause for example,
AND (IF #NonCAT = 'NonCAT'
BEGIN
CASE
WHEN il.CATCOD IN ('0', '114', '214', '314', '414', '614')
THEN 'NonCAT'
ELSE 'CAT'
END = #NonCAT
END)
Seems like that doesn't work. I can use an IF statement at the very begging of the code as a flag but that doesn't seem very efficient because I would have to rewrite the whole thing without a where clause if that makes sense.
You mean something like this?
WHERE ( ( #nonCAT = 'nonCAT' AND il.CATCOD IN ('0', '114', '214', '314', '414', '614') )
OR ( (ISNULL(#nonCAT,'') <> 'nonCAT' ))
I need a regex that will determine if a given SQL statement has a WHERE clause. My problem is that the passed SQL statements will most likely be complex, so I can not rely on just the existence of the word WHERE in the statement.
For example this should match
SELECT Contacts.ID
, CASE WHEN (Contacts.Firstname IS NULL) THEN ''
ELSE CAST(Contacts.Firstname AS varchar)
END AS Firstname
, CASE WHEN (Contacts.Lastname IS NULL) THEN ''
ELSE CAST(Contacts.Lastname AS varchar)
END AS Lastname
, CASE WHEN (tbl_ContactExtras.Prequalified=-1 OR
tbl_ContactExtras.Prequalified IS NULL) THEN ''
WHEN tbl_ContactExtras.Prequalified=0 THEN 'No'
WHEN tbl_ContactExtras.Prequalified=1 THEN 'Yes - Other'
WHEN tbl_ContactExtras.Prequalified=2 THEN 'Yes'
ELSE CAST(tbl_ContactExtras.Prequalified AS varchar)
END AS Prequalified
FROM contacts
LEFT JOIN tbl_ContactExtras
ON tbl_ContactExtras.ContactID = Contacts.ID
WHERE (Contacts.Firstname LIKE 'Bob%')
and this should not match:
SELECT Contacts.ID
, CASE WHEN (Contacts.Firstname IS NULL) THEN ''
ELSE CAST(Contacts.Firstname AS varchar)
END AS Firstname
, CASE WHEN (Contacts.Lastname IS NULL) THEN ''
ELSE CAST(Contacts.Lastname AS varchar)
END AS Lastname
, CASE WHEN (tbl_ContactExtras.Prequalified=-1 OR
tbl_ContactExtras.Prequalified IS NULL) THEN ''
WHEN tbl_ContactExtras.Prequalified=0 THEN 'No'
WHEN tbl_ContactExtras.Prequalified=1 THEN 'Yes - Other'
WHEN tbl_ContactExtras.Prequalified=2 THEN 'Yes'
ELSE CAST(tbl_ContactExtras.Prequalified AS varchar)
END AS Prequalified
FROM contacts
LEFT JOIN tbl_ContactExtras
ON tbl_ContactExtras.ContactID = Contacts.ID
Those are examples of some of the simpler statements: a statement could have up to 30 CASE statements in it, or it could have none at all.
I need to programmatically add WHERE parameters, but doing this correctly requires knowing whether a WHERE clause is already present.
Any idea on a regex that would work for this? If not, any other ideas on how to tell the two apart?
Thanks,
This is not possible, since a WHERE clause may be arbitrarily nested inside the FROM clause.
This may not catch all cases but you may find you can catch most of them just by finding the last from and the last where in the statement.
if the where is after the from, then it has a where clause. If the where is before the from (or there is no where at all), then no where clause exists.
Sometimes, it's okay to leave restrictions or limitations in your code, as long as they're properly documented.
For example, I've worked on a project before that parsed SQL and we discovered it didn't handle things like between:
where recdate between '2010-01-01' and '2010-12-31'
Rather than spend a bucket-load of money fixing the problem (and probably introducing bugs on the way), we simply published it as a restriction and told everyone they had to change it to:
where recdate >= '2010-01-01'
and recdate <= '2010-12-31'
Problem solved. While it's good to keep customers happy, you don't have to cater to every whim :-)
Other than that, you need an SQL parser, and SQL is not a pretty language to parse, trust me on that one.
Are all of the joins the same? If so you could find the index of all or part of the FROM statement (perhaps using a regex to be tolerant of slight differences in syntax and whitespace) and then look for the occurrence of the word WHERE after that index.
In general you would be better off using a parser. But if this is just a one off thing and the statements are all fairly similar then the above approach should be okay.
Regex is not designed to do this. Parsing SQL properly requires matching balanced parentheses (and other matching pairs, such as quotes), something regex is not designed to do (and pure regex isn't even equipped to; PCRE can but it's not pretty).
Instead, just write a basic state machine or something to parse it.
What's the problem you're trying to solve? Are you trying to determine if it's safe to add constraints to these existing queries?
For example, if you've got this query
...
where foo = 'bar'
then you know it's safe to add
and bat = 'quux'
but if you don't have a WHERE clause already, then you have to do it as
where bat = 'quux'
Is that the problem you're trying to solve? If so, can you make every SQL query you're working with have a WHERE clause by adding a "WHERE 0=0" to those queries that don't have one? Then you know in your post-process phase that every query already has one.
This is just a guess, of course. Your question sounded like that might be the larger issue.