How to set a NULL when entering NULL keeps the old value - sql

I have a stored procedure where it is able to update the 4 columns below as there are 4 parameters (1 parameter for each column with ClawbackID the only one that doesn't change).
Now there is no fixed amount of columns that can be updated, I may choose to update 1 column, or 3 columns or all 4 columns. So to reduce human error, I have a coalesce so that if the user enters in 'NULL' for a particular parameter whilst executing a procedure, the original amount stays.
Example for row 3 for 'ClawbackAmount', if I enter in NULL and execute, it will still display the 'ClawbackAmount' 900.54. Now the problem I have is that actually want to set this amount to 'NULL', but I don't want to lose the functionality that if I type in 'NULL' when executing my procedure that it keeps the old value.
My question is that is there a way or an idea you can think of where I type in NULL then the default values stays but if I type in something like '' then it will default to 'NULL'?
Or alternatively type in the word 'SAME' to keep the default value and then type in 'NULL' for a null value? Just ideas really to get around it?
Below is the code I have with the parameters included as they begin with #:
update clw
set clw.PaymentID = Coalesce(#PaymentID, clw.PaymentId)
,clw.ClawbackDate = Coalesce(#ClawbackDate, clw.ClawbackDate)
, clw.ClawbackPercent = Coalesce(#ClawbackPercent, clw.ClawbackPercent)
, clw.ClawbackAmount = Coalesce(#ClawbackAmount,clw.ClawbackAmount)
OUTPUT '[Fees].EBD.Clawback' 'TableName','ClawbackId', inserted.ClawbackId,
Core.updXMLFragment('PaymentId', inserted.PaymentId, deleted.PaymentId) +
Core.updXMLFragment('ClawbackDate', Convert(varchar(50),inserted.ClawbackDate, 112), Convert(varchar(50),deleted.ClawbackDate, 112)) +
Core.updXMLFragment('ClawbackPercent', inserted.ClawbackPercent, deleted.ClawbackPercent) +
Core.updXMLFragment('ClawbackAmount', inserted.ClawbackAmount, deleted.ClawbackAmount)
INTO #OutputList
from [Fees].EBD.Clawback clw
Where
ClawbackId = #ClawbackID
Below is the code for the execution as an example for row 3 if I want to make the desired change:
First Param is ClawbackID (this doesn't change but need it to know which row to manipulate.
Second Param is PaymentID which is NULL as want to keep the same
Third Param is Clawbackdate which is NULL as want to keep the same
Fourth Param is ClawbackPercent which needs to be 0.25
Last Param is ClawbackAmount which I need to set to NULL. This is an int field btw but leaving it NULL will keep the orginal amount displayed.
exec SupportAudit.BI.UpdateHotelClawback 28817, NULL, NULL, 0.25, NULL

I generally use some specific invalid value as an indicator the column should be set to NULL. In the case of ClawbackPercent and ClawbackAmount, -1 seems like a good candidate. The change would look like this:
...
, clw.ClawbackPercent = NullIf(Coalesce(#ClawbackPercent, clw.ClawbackPercent), -1)
, clw.ClawbackAmount = NullIf(Coalesce(#ClawbackAmount,clw.ClawbackAmount), -1)
...
For string parameters, '' (the empty string) might be an appropriate choice.

Related

Oracle ERROR-01722 not showing up consistently

There seems to be inconsistencies with how ERROR-01722 error worked, for those who don't know the issue is due to an invalid number and to fix it you'll need to wrap the number to char.
But when filtering VARCHAR2 it is stated that Oracle will convert the data of the column being filtered based on the value given to it. (see: https://stackoverflow.com/a/10422418/5337433)
Now that this is explained for some reason, the error is inconsistent. As an example I have this query:
In this example filter1 is varchar2
select *
from table
where filter1 = 12345
and filter2 = ''
and filter3 = '';
When this statement run there were no issues, but when you run it like this:
select *
from table
where filter1 = 12345
and filter2 = '';
it errors out to ERROR-01722, im not sure why it is acting this way, and how to fix it.
When you compare a varchar column to a number, Oracle will try to convert the column's content to a number, not the other way round (because 123 could be stored as '0123' or '00123')
In general you should always use constant values that match the data type of the column you compare them with. So it should be:
where filter1 = '12345'
However if you are storing numbers in that column, you should not define it as varchar - it should be converted to a proper number column.
The reason the error doesn't show up "consistently" is that you seem to have some values that can be converted to a number and some can't. It depends on other conditions in the query if the those values are included or not.
Additionally: empty strings are converted to NULL in Oracle. So the condition filter2 = '' will never be true. You will have to use filter2 is null if you want to check for an "empty" column.

T-SQL concatenation issue with NULLS

I'm trying to do a simple concatenation but failing somewhere! I want to display the Note in the email only if the other two variables are not empty. Even if one variable contains data it should display the Note. Below is my code.
SET #Note = CASE
WHEN #tableHTML_AssignedTo IS NOT NULL OR #tableHTML_SubmittedBy IS NOT NULL
THEN 'Note: The tickets with the following statuses are not listed in this alert: Closed,Rejected'
ELSE NULL
END
SET #ComposeBody = ISNULL(#tableHTML_AssignedTo, '') +
ISNULL(#tableHTML_SubmittedBy, '') +
ISNULL(#Note, '')
I know it's simple code but it's not obvious to my mind what I'm doing wrong. But with my code, an empty email is sent if both the tables are empty with Notes. If I remove Notes, no email is sent but I want to add the Notes in the email
Note: I'm executing this code inside cursor to send emails recursively
I'd do it like this -- seems simpler.
The trick here is to understand how null works with concat. Anything concat with null is null. So the first parameter to COALESCE will be null if Assigned or submitted is null. Each next step checks the other two cases.
SET #Note = 'Note: The tickets with the following statuses are not listed in this alert: Closed,Rejected';
SET #ComposeBody = COALESCE(
#tableHTML_AssignedTo+#tableHTML_SubmittedBy+#Note, -- Selected if both non null
#tableHTML_AssignedTo+#Note, -- Selected if SubmittedBy null
#tableHTML_SubmittedBy+#Note) -- Selected if AssignedTo null
-- Both are null, set body to null.

STUFF function sql returns null?

I have a specific column in a table, it shall contains only numbers in Nvarchar that have a length of 3. Unfortunately, some users wrote '12' but they should have written '012'. There were not enough validation at the time.
I need to fix that. Here is the logic I used :
UPDATE [Mandats_Approvisionnement].[dbo].[ARTICLE_ECOLE]
SET [UNIT_ADM] = STUFF(UNIT_ADM, 0, 0, '0')
WHERE LEN(UNIT_ADM) = 2;
The error goes like :
Cannot insert the value NULL into column 'UNIT_ADM', table
'Mandats_Approvisionnement.dbo.ARTICLE_ECOLE'; column does not allow
nulls. UPDATE fails.
I can't see where the problem is, I verified and all the records contain at least 2 characters, so the STUFF function cannot returns null as there are no NULL records in that table column [unit_adm]... How do I make it work ?
It should be stuff(UNIT_ADM,1,0,'0') as stuff returns null if the start position is 0.
Citing the documentation:
If the start position or the length is negative, or if the starting
position is larger than length of the first string, a null string is
returned. If the start position is 0, a null value is returned.
You could make this simpler by using
right('0' + UNIT_ADM, 3)
instead of stuff.

Set blank result equal to specific string in SQL Server

I have a query that returns a result set which contains a certain column that needs some tweaking. Basically, in the result set, there are certain rows that contain a blank value for the applicable column. What I need to do is set all instances of that blank value to a specific string. I have tried declaring a variable and setting the variable equal to the column name (using a SELECT statement) and then using an IF statement to set the value to a specific string if it is blank (' '). My code thus far is as follows:
declare #sourceNode varchar(30)
set #sourceNode = (select sn_name from pt_cust)
if #sourceNode = '' begin
set #sourceNode = 'None'
end
This code returns an error stating that the sub-query returns more than 1 value. This seems like an easy task but I am stuck at the moment. How can this be accomplished?
This is a case (heh) for CASE:
SELECT CASE WHEN sn_name = '' THEN 'None' ELSE sn_name END
FROM pt_cust
You are getting the error message you mentioned because your SELECT statement can return more than one row, in which case it can not be assigned to a variable.

Replacing a calculated field column with a Blank when a NULL is returned?

I'm doing a simple query that uses the DateDiff function to find the number of days between the dates. However, with regards to certain instances, I'd like to populate a blank field (not a null).
Something like this is what I currently have, and it seems to work fine (but it populates a null).
[Test (Years)] = CASE WHEN TYPE IN ('A','B')
THEN NULL ELSE IsNull(CONVERT(decimal(28,12),
(DATEDIFF(d,#StartDate,ExpirationDate)))/365,0) END
Now if I try something like this... which tries to convert all TYPE A and B to populate a blank, I'll get the following error message: Error converting data type varchar to numeric.
[Test (Years)] = CASE WHEN TYPE IN ('A','B')
THEN '' ELSE IsNull(CONVERT(decimal(28,12),
(DATEDIFF(d,#StartDate,ExpirationDate)))/365,0) END
Is there a simple thing I'm missing? I've tried doing the calcualtions without converting to a decimal, but it doesn't seem to work. Any ideas? Thanks
CASE is an expression that returns exactly one value and all of the branches must yield compatible types. A string (even a blank string) is not compatible with a decimal, so you need to do something like:
CASE WHEN ... THEN '' ELSE
CONVERT(VARCHAR(32), COALESCE(CONVERT(DECIMAL(23,12), ... ,0)) END
Note that this hack will only work if you are presenting the data to an end user. If you are trying to store this data in a column or use it in other calculations, it too will be tripped up by the blank string. A number can't be a blank string:
DECLARE #i INT = '';
SELECT #i;
Result:
0
So, if you don't want "empty" numerics to be interpreted as 0, stop being afraid of NULL and if you are dealing with this at presentation time, have the presentation layer present a blank string instead of NULL.