TSQL Format SSN/TIN (SQL Server 2016+) - sql

I need to format US SSN/TIN strings with dashes when they appear to be valid
(where valid = 9 digits) and otherwise return what is in the field (with leading 0s).
123456789 should format to 123-45-6789
and 3456789 formats to 003-45-6789
Can someone tell me why this code doesn't work?
Declare #TaxIDNum VarChar(11)
Set #TaxIDNum = '3456789'
Set #TaxIDNum = Right('0000'+#TaxIDNum,9)
Set #TaxIDNum =
CASE #TaxIDNum WHEN Len(#TaxIDNum)=9 THEN
CASE #TaxIDNum
WHEN IsNumeric(#TaxIDNum)
THEN Left(#TaxIDNum,3)+'-'+Right(Left(#TaxIDNum,5),2)+'-'+Right(#TaxIDNum,4)
ELSE #TaxIDNum END -- return existing value
ELSE #TaxIDNum END -- return existing value
select #TaxIDNum, len(#TaxIDNum) as Length
I get a red squiggly error on the equals in "=9":
(Error text is: "Incorrect syntax near '='.")
Any solution that both works with a select or set, and solves the problem is welcome.
Thanks to #Larnu for mentioning Set #TaxIDNum=FORMAT(CONVERT(int,#TaxIDNum),'000-00-0000')
If I had error handling (our SSvr install doesn't) I would use Format. However if there is bad data, it breaks my query in a way from which I cannot recover.
Set #TaxIDNum=Replace('123-45-6789','-','') does avoid errors if the only data problem is that some of the rows are already formatted.

Seems like you could use FORMAT:
SELECT FORMAT(CONVERT(int,#TaxIDNum),'000-00-0000');

Why it does not work
From comments by [HABO][1]
You have mixed simple and searched case syntaxes, hence the complaint.
You should use LIKE (learn.microsoft.com/en-us/sql/t-sql/language-elements/…)
with a suitable pattern, e.g.
'[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]', to determine if the
string contains only nine numeric characters.
So I tried this, which also didn't work:
SET #TaxIDNum =
CASE #TaxIDNum Like '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
WHEN true
THEN …
HABO:
You've hit an fiendish edge case.
There is a boolean data type (with
values TRUE, FALSE and UNKNOWN), but you cannot get a firm grip on
one:
"Unlike other SQL Server data types, a Boolean data type cannot
be specified as the data type of a table column or variable, and
cannot be returned in a result set."
You can't have CASE «boolean-expression» WHEN true THEN «result» END
Solution:
Use LIKE leaving the CASE expression empty
declare #TaxIDNum VarChar(11)
set #TaxIDNum='3456789'
set #TaxIDNum=right('0000'+#TaxIDNum,9)
select #TaxIDNum
SET #TaxIDNum = CASE
WHEN #TaxIDNum Like '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
THEN Left(#TaxIDNum,3)+'-'+SubString(#TaxIDNum,4,2)+'-'+Right(#TaxIDNum,4)
ELSE #TaxIDNum END
select #TaxIDNum

Related

Setting BIT variable using CASE statements

I'm in the middle of a migration that uses some reporting elements from Crystal and attempting to convert what existed previously into SQL. It looks to use VB scripting but I can't figure out how to make the switch over.
Initially I'd assume a CASE WHEN statement would suffice but I can't determine the right logic behind the query.
Sample of the VB below:
Dim HasValue As Boolean
If isnull({Reference.Shallow}) Then
HasValue=False
formula="MISSING"
Else
HasValue=True
End If
I am aware that IF does exist in SQL Server but when researching it, people tend to stray away from it as CASE WHEN does the same?
I have some psuedo that I'd imagine should work in the same way but this does not resolve as you cannot set a variable within a CASE WHEN statement (I believe):
DECLARE HasValue BIT
CASE WHEN Reference.Shallow IS NULL
THEN SET #HasValue = 1
ELSE SET #HasValue = 0
END AS Shallow
What would be the most appropriate way of doing this within SQL?
You must use this code snippet
DECLARE #HasValue BIT
SELECT #HasValue=CASE WHEN Shallow IS NULL THEN CAST(1 AS BIT) ELSE CAST(0 AS
BIT) END FROM Reference.Shallow
CASE returns a scalar value, not a operation or boolean result. You set the value of the variable to the result of the CASE:
SET #HasValue = (SELECT CASE WHEN R.Shallow IS NULL THEN 1 ELSE 0 END
FROM dbo.Reference R
/*WHERE...? */);

Like with Regular Expression not giving right result in sql server

declare #test varchar(50)
set #test='sad#fd'
if #test LIKE '%[a-zA-Z0-9 ./,()?''+-]%'
print 'yes'
else
print 'no'
My above code giving yes result as it should give no as I am not allowing '#' in regular expression. Is there anything wrong?
I want to handle this in my stored procedure where string is alpha numeric with specified list of special character allowed. What should I do?
The result is "Yes", because u have an letter s which is matching the condition
to get more clear, try running the below code
declare #test varchar(1000)
set #test='####'
if #test LIKE '%[a-zA-Z0-9 ./,()?''+-]%'
print 'yes'
else
print 'no'
SQL Server doesn't really have native regular expressions1, but what you're trying to achieve can still be done with LIKE by introducing a double negative:
declare #test varchar(50)
set #test='sad#fd'
if #test NOT LIKE '%[^a-zA-Z0-9 ./,()?''+-]%'
print 'yes'
else
print 'no'
% matches any number of characters. ^ inverts a character range. So, now we're asking - is the string any number of characters, then a character not in the set a-zA-Z0-9 ./,()?''+-, then any number of characters? - or, to put it another way, does this string contain any characters outside of the given set of characters?
1You can access a fully featured regex engine from the .NET framework by using the CLR integration. It's one of the usual samples given when talking about CLR integration. But not really needed here.

Cast as INT check SQL

I need to update a column in a table. But only where the cast to an INT fails.
I have the following so far - but this updates all the records.
begin try
select cast(customerid as int) from Table_staging;
end try
begin catch
update Table_staging
set incorrectformat = 0
end catch
update Table_staging
set incorrectformat = 0
where not customerid like '%[^0-9]%'
should be sufficient. Basically, we mark incorrectformat for any row where customerid is not a string that contains any number of characters, then a character not in the set 0-9, than any number of characters.
I.e. the values that don't match this are precisely the ones only containing digits.
And the main issue with ISNUMERIC is that it answers a question that I don't believe anyone would ever, rightfully, ask - "Can this character string be converted to any of the numeric data types? I don't care which of those types it can be converted to, and there's no need to tell me which ones in response either"

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.