How to validate string in SQL with characters - sql

Check if the string is following the correct format or not. The correct format is as follows:
0000/00000. So far this is what i have got:
declare #ID nvarchar = '0000/00000'
SELECT (case when len(#id) not between 1 and 12 OR #id not like( '[0-9][0-9][0-9][0-9]' + '/' + '[0-9][0-9][0-9][0-9][0-9]')
OR LEFT(#id,13) LIKE '%[0-9]&' then 'OK' else 'ERROR' end

Why not just use not like?
where #id not like '[0-9][0-9][0-9][0-9]/[0-9][0-9][0-9][0-9][0-9]'
I assume that "0" means that any digit is allowed.

First, this will be a problem:
declare #ID nvarchar = '0000/00000'
This:
declare #ID nvarchar = '0000/00000';
SELECT #ID LEN(#ID), DATALENGTH(#ID);
Returns:
ID LEN
---- ----
0 1
With that in mind, note that this: PATINDEX({your pattern},#Id) will return a natural Boolean result.
DECLARE #ID1 NVARCHAR(1000) = '5555/12312',
#ID2 NVARCHAR(1000) = '1234/12345678',
#pattern VARCHAR(100) = '[0-9][0-9][0-9][0-9]/[0-9][0-9][0-9][0-9][0-9]';
SELECT IsCool = PATINDEX(#pattern,f.Id)
FROM (VALUES(#ID1),(#ID2)) AS f(Id);
Returns:
IsCool
-----------
1
0
If, by 0000/00000 you mean: Four digits + "/" + five digits then these expressions all work (note I made the pattern a variable for cleaner, easier to read code, it's not required):
DECLARE #ID NVARCHAR(1000) = '5555/12312',
#pattern VARCHAR(100) = '[0-9][0-9][0-9][0-9]/[0-9][0-9][0-9][0-9][0-9]';
SELECT CASE PATINDEX(#Pattern,#ID) WHEN 1 THEN 'Ok' ELSE 'Error' END;
SELECT IIF(PATINDEX(#Pattern,#ID)>0,'Ok','Error');
SELECT CHOOSE(PATINDEX(#Pattern,#ID)+1,'Error','Ok');
Your code suggests that #ID can be up to 12 characters long. Let's say, for example, the acceptable formats were:
0000/00000
0000/000000
0000/0000000
Then you could do this:
DECLARE #ID NVARCHAR(1000) = '5555/12312';
SELECT CASE WHEN LEN(#ID)<13 AND SIGN(PATINDEX('%[0-9][0-9]',#ID)) *
PATINDEX('[0-9][0-9][0-9][0-9]/[0-9][0-9][0-9][0-9][0-9]%',#ID) = 1
THEN 'Ok' ELSE 'Error' END;
Two final thoughts:
LEN({string}) can't be negative; LEN(#ID) < 13 will do the trick
If the max length is really 12 then make the parameter or variable NVARCHAR(13). This way, for example, someone passes in an 8000 character string, SQL doesn't have to scan the whole thing to determine that it's not valid.

Related

Executing select statement as variable from TVF

I have to get a list of results from a Table value function from a variable. I have done something like this:
DECLARE #Date char(8) = '20200508'
DECLARE #Type varchar(100) = 'Inbound'
DECLARE #Offset INT = 3600
DECLARE #EmployeeID INT = null
DECLARE #TypeFunc as varchar(max)
SET #TypeFunc= N'select EmpID, Callcount from dbo.fn_' + #Type + '('''+ #Date +''','+ CAST(#Offset as Varchar(100))+','+ CAST(#EmployeeID as varchar(100))+')';
EXEC (#TypeFunc)
I expect to see a list of results as if I'm doing a normal select query, however, it is just coming back with 'Commands completed successfully.' in the results grid, which doesn't seem like its doing it correctly.
The query it should run should look like
Select EmpID, Callcount From dbo.fn_Inbound('20200508', 3600, null)
Anything I'm missing here?
I found 2 mistakes in your Query:
1.) Use CONCAT instead of + because if any of your concatenating string is null it makes the whole Concatenation as NULL (For your case EmpID is null it will makes the Whole Query as null by using +)
2.)ISNULL(CAST(#EmployeeID as varchar(100)),'NULL') Use ISNULL fn to pass as null for that Parameter in your function
SET #TypeFunc= CONCAT(N'select EmpID, Callcount from dbo.fn_' , #Type , '(''', #Date
,''',', CAST(#Offset as Varchar(100)),',',ISNULL(CAST(#EmployeeID as
varchar(100)),'NULL'),')');

SQL function to split a string into characters

I hava an ID column in my database, and it shows the results as follows
1121
1232
1233
and i want to get an extra column where i can have their sums as follows
5
8
9
can anyone help me which sql function should i use to break a string into characters and add them?
Assuming a number that is always 4 digits long, you can simply do this:
select (id/1000)+((id%1000)/100)+((id%100)/10)+(id%10)
If the ID field is varchar, just cast it to an int before division. Of course, if the result of this has more than 1 digit, you will not be able to get the sum of its digits again.
You could use this table-valued function:
CREATE FUNCTION [dbo].[Chars]
(
#Text NVARCHAR(MAX)
)
RETURNS #ItemTable TABLE (Item VARCHAR(250))
AS
BEGIN
DECLARE #i INT
DECLARE #Item NVARCHAR(4000)
SET #i = 1
WHILE (#i <= LEN(#Text))
BEGIN
INSERT INTO #ItemTable(Item)
VALUES(SUBSTRING(#Text, #i, 1))
SET #i = #i + 1
END
RETURN
END
Now this query should work as desired:
SELECT t.ID, SUM(CAST(Split.Item AS INT)) AS SumID
FROM dbo.TableName t
CROSS APPLY dbo.Chars(CONVERT(varchar(10), t.ID))Split
GROUP BY t.ID
Here's a demo: http://sqlfiddle.com/#!3/8eea7/8/0

Split words with a capital letter in sql

Does anyone know how to split words starting with capital letters from a string?
Example:
DECLARE #var1 varchar(100) = 'OneTwoThreeFour'
DECLARE #var2 varchar(100) = 'OneTwoThreeFourFive'
DECLARE #var3 varchar(100) = 'One'
SELECT #var1 as Col1, <?> as Col2
SELECT #var2 as Col1, <?> as Col2
SELECT #var3 as Col1, <?> as Col2
expected result:
Col1 Col2
OneTwoThreeFour One Two three Four
OneTwoThreeFourFive One Two Three Four Five
One One
If this is not possible (or if too long) an scalar function would be okay as well.
Here is a function I created that is similar to the "removing non-alphabetic characters". How to strip all non-alphabetic characters from string in SQL Server?
This one uses a case sensitive collation which actively seeks out a non-space/capital letter combination and then uses the STUFF function to insert the space. This IS a scalar UDF, so some folks will immediately say that it will be slower than other solutions. To that notion, I say, please test it. This function does not use any table data and only loops as many times as necessary, so it will likely give you very good performance.
Create Function dbo.Split_On_Upper_Case(#Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin
Declare #KeepValues as varchar(50)
Set #KeepValues = '%[^ ][A-Z]%'
While PatIndex(#KeepValues collate Latin1_General_Bin, #Temp) > 0
Set #Temp = Stuff(#Temp, PatIndex(#KeepValues collate Latin1_General_Bin, #Temp) + 1, 0, ' ')
Return #Temp
End
Call it like this:
Select dbo.Split_On_Upper_Case('OneTwoThreeFour')
Select dbo.Split_On_Upper_Case('OneTwoThreeFour')
Select dbo.Split_On_Upper_Case('One')
Select dbo.Split_On_Upper_Case('OneTwoThree')
Select dbo.Split_On_Upper_Case('stackOverFlow')
Select dbo.Split_On_Upper_Case('StackOverFlow')
Here is a function I have just created.
FUNCTION
CREATE FUNCTION dbo.Split_On_Upper_Case
(
#String VARCHAR(4000)
)
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE #Char CHAR(1);
DECLARE #i INT = 0;
DECLARE #OutString VARCHAR(4000) = '';
WHILE (#i <= LEN(#String))
BEGIN
SELECT #Char = SUBSTRING(#String, #i,1)
IF (#Char = UPPER(#Char) Collate Latin1_General_CS_AI)
SET #OutString = #OutString + ' ' + #Char;
ELSE
SET #OutString = #OutString + #Char;
SET #i += 1;
END
SET #OutString = LTRIM(#OutString);
RETURN #OutString;
END
Test Data
DECLARE #TABLE TABLE (Strings VARCHAR(1000))
INSERT INTO #TABLE
VALUES ('OneTwoThree') ,
('FourFiveSix') ,
('SevenEightNine')
Query
SELECT dbo.Split_On_Upper_Case(Strings) AS Vals
FROM #TABLE
Result Set
╔══════════════════╗
║ Vals ║
╠══════════════════╣
║ One Two Three ║
║ Four Five Six ║
║ Seven Eight Nine ║
╚══════════════════╝
If a single query is needed 26 REPLACE can be used to check every upper case letter like
SELECT #var1 col1, REPLACE(
REPLACE(
REPLACE(
...
REPLACE(#var1, 'A', ' A')
, ...
, 'X', ' X')
, 'Y', ' Y')
, 'Z', ' Z') col2
Not the most beautiful thing but it'll work.
EDIT
Just to add another function to do the same thing in a different way of the other answers
CREATE FUNCTION splitCapital (#param Varchar(MAX))
RETURNS Varchar(MAX)
BEGIN
Declare #ret Varchar(MAX) = '';
declare #len int = len(#param);
WITH Base10(N) AS (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
UNION ALL SELECT 8 UNION ALL SELECT 9
), Chars(N) As (
Select TOP(#len)
nthChar
= substring(#param, u.N + t.N*10 + h.N*100 + th.N*1000 + 1, 1)
Collate Latin1_General_CS_AI
FROM Base10 u
CROSS JOIN Base10 t
CROSS JOIN Base10 h
CROSS JOIN Base10 th
WHERE u.N + t.N*10 + h.N*100 + th.N*1000 < #len
ORDER BY u.N + t.N*10 + h.N*100 + th.N*1000
)
SELECT #ret += Case nthChar
When UPPER(nthChar) Then ' '
Else ''
End + nthChar
FROM Chars
RETURN #ret;
END
This one uses the possibility of TSQL to concatenate string variable, I had to use the TOP N trick to force the Chars CTE rows in the right order
Build a Numbers table. There are some excellent posts on SO to show you how to do this. Populate it with values up the maximum length of your input string. Select the values from 1 through the actual length of the current input string. Cross join this list of numbers to the input string. Use the result to SUBSTRING() each character. Then you can either compare the resulting list of one-charachter values to a pre-populated table-valued variable or convert each character to an integer using ASCII() and choose only those between 65 ('A') and 90 ('Z'). At this point you have a list which is the position of each upper-case character in your input string. UNION the maximum length of your input string onto the end of this list. You'll see why in just a second. Now you can SUBSTRING() your input variable, starting at the Number given by row N and taking a length of (the Number given by row N+1) - (The number given by row N). This is why you have to UNION the extra Number on the end. Finally concatenate all these substring together, space-separated, using the algorithm of your choice.
Sorry, don't have an instance in front of me to try out code. Sounds like a fun task. I think doing it with nested SELECT statements will get convoluted and un-maintainable; better to lay it out as CTEs, IMHO.
I know that there are already some good answers out there, but if you wanted to avoid creating a function, you could also use a recursive CTE to accomplish this. It's certainly not a clean way of doing this, but it works.
DECLARE
#camelcase nvarchar(4000) = 'ThisIsCamelCased'
;
WITH
split
AS
(
SELECT
[iteration] = 0
,[string] = #camelcase
UNION ALL
SELECT
[iteration] = split.[iteration] + 1
,[string] = STUFF(split.[string], pattern.[index] + 1, 0, ' ')
FROM
split
CROSS APPLY
( SELECT [index] = PATINDEX(N'%[^ ][A-Z]%' COLLATE Latin1_General_Bin, split.[string]) )
pattern
WHERE
pattern.[index] > 0
)
SELECT TOP (1)
[spaced] = split.[string]
FROM
split
ORDER BY
split.[iteration] DESC
;
As I said, this isn't a pretty way to write a query, but I use things like this when I'm just writing up some ad-hoc queries where I would not want to add new artifacts to the database. You could also use this to create your function as an inline table valued function, which is always a tad nicer.
Please Try This:
declare #t nvarchar (100) ='IamTheTestString'
declare #len int
declare #Counter int =0
declare #Final nvarchar (100) =''
set #len =len( #t)
while (#Counter <= #len)
begin
set #Final= #Final + Case when ascii(substring (#t,#Counter,1))>=65 and
ascii(substring (#t,#Counter,1))<=90 then ' '+substring (#t,#Counter,1) else
substring (#t,#Counter,1) end
set #Counter=#Counter+1
end
print ltrim(#Final)

Is it possible to compare rows for similar data in SQL server

Is it possible to compare rows for similar data in SQL Server? I have a company name column in a table where company names could be somewhat similar. Here is an example of the different 8 values that represent the same 4 companies:
ANDORRA WOODS
ANDORRA WOODS HEALTHCARE CENTER
ABC HEALTHCARE, JOB #31181
ABC HEALTHCARE, JOB #31251
ACTION SERVICE SALES, A SUBSIDIARY OF SINGER EQUIPMENT
ACTION SERVICE SALES, A SUBSIDIARY OF SINGER EQUIPMENT COMPANY
APEX SYSTEMS
APEX SYSTEMS, INC
The way I clean it right now is using Google refine where I can identify clusters of similar data values and make them all as one.
Using this example I only need 4 names not 8 so I need to replace similar ones with only one since I will be assigning indexes to those names later on. Any help is greatly appreciated.
I have a couple UDF's I converted from some VB code some time ago that takes in 2 varchar() and returns an int between 0 and 100 (0= not similar, 100= same) if your interested.
-- Description: Removes any special characters from a string
CREATE FUNCTION [dbo].[SimReplaceSpecial]
(
-- Add the parameters for the function here
#String varchar(max)
)
RETURNS varchar(max)
AS
BEGIN
-- Declare the return variable here
DECLARE #Result varchar(max) = ''
-- Add the T-SQL statements to compute the return value here
DECLARE #Pos int = 1
DECLARE #Asc int
DECLARE #WorkingString varchar(max)
SET #WorkingString = upper(#String)
WHILE #Pos <= LEN(#WorkingString)
BEGIN
SET #Asc = ascii(substring(#WorkingString,#Pos,1))
If (#Asc >= 48 And #Asc <= 57) Or (#Asc >= 65 And #Asc <= 90)
SET #Result = #Result + Char(#Asc)
SET #Pos = #Pos + 1
--IF #Pos + 1 > len(#String)
-- BREAK
--ELSE
-- CONTINUE
END
-- Return the result of the function
RETURN #Result
END
-- Description: DO NOT CALL DIRECTLY - Used by the Similar function
-- Finds longest common substring (other than single
-- characters) in String1 and String2, then recursively
-- finds longest common substring in left-hand
-- portion and right-hand portion. Updates the
-- cumulative score.
CREATE FUNCTION [dbo].[SimFindCommon]
(
-- Add the parameters for the function here
#String1 varchar(max),
#String2 varchar(max),
#Score int
)
RETURNS int
AS
BEGIN
-- Declare the return variable here
--DECLARE #Result int
DECLARE #Longest Int = 0
DECLARE #StartPos1 Int = 0
DECLARE #StartPos2 Int = 0
DECLARE #J Int = 0
DECLARE #HoldStr varchar(max)
DECLARE #TestStr varchar(max)
DECLARE #LeftStr1 varchar(max) = ''
DECLARE #LeftStr2 varchar(max) = ''
DECLARE #RightStr1 varchar(max) = ''
DECLARE #RightStr2 varchar(max) = ''
-- Add the T-SQL statements to compute the return value here
SET #HoldStr = #String2
WHILE LEN(#HoldStr) > #Longest
BEGIN
SET #TestStr = #HoldStr
WHILE LEN(#TestStr) > 1
BEGIN
SET #J = CHARINDEX(#TestStr,#String1)
If #J > 0
BEGIN
--Test string is sub-set of the other string
If Len(#TestStr) > #Longest
BEGIN
--Test string is longer than previous
--longest. Store its length and position.
SET #Longest = Len(#TestStr)
SET #StartPos1 = #J
SET #StartPos2 = CHARINDEX(#TestStr,#String2)
END
--No point in going further with this string
BREAK
END
ELSE
--Test string is not a sub-set of the other
--string. Discard final character of test
--string and try again.
SET #TestStr = Left(#TestStr, LEN(#TestStr) - 1)
END
--Now discard first char of test string and
--repeat the process.
SET #HoldStr = Right(#HoldStr, LEN(#HoldStr) - 1)
END
--Update the cumulative score with the length of
--the common sub-string.
SET #Score = #Score + #Longest
--We now have the longest common sub-string, so we
--can isolate the sub-strings to the left and right
--of it.
If #StartPos1 > 3 And #StartPos2 > 3
BEGIN
SET #LeftStr1 = Left(#String1, #StartPos1 - 1)
SET #LeftStr2 = Left(#String2, #StartPos2 - 1)
If RTRIM(LTRIM(#LeftStr1)) <> '' And RTRIM(LTRIM(#LeftStr2)) <> ''
BEGIN
--Get longest common substring from left strings
SET #Score = dbo.SimFindCommon(#LeftStr1, #LeftStr2,#Score)
END
END
ELSE
BEGIN
SET #LeftStr1 = ''
SET #LeftStr2 = ''
END
If #Longest > 0
BEGIN
SET #RightStr1 = substring(#String1, #StartPos1 + #Longest, LEN(#String1))
SET #RightStr2 = substring(#String2, #StartPos2 + #Longest, LEN(#String2))
If RTRIM(LTRIM(#RightStr1)) <> '' And RTRIM(LTRIM(#RightStr2)) <> ''
BEGIN
--Get longest common substring from right strings
SET #Score = dbo.SimFindCommon(#RightStr1, #RightStr2,#Score)
END
END
ELSE
BEGIN
SET #RightStr1 = ''
SET #RightStr2 = ''
END
-- Return the result of the function
RETURN #Score
END
-- Description: Compares two not-empty strings regardless of case.
-- Returns a numeric indication of their similarity
-- (0 = not at all similar, 100 = identical)
CREATE FUNCTION [dbo].[Similar]
(
-- Add the parameters for the function here
#String1 varchar(max),
#String2 varchar(max)
)
RETURNS int
AS
BEGIN
-- Declare the return variable here
DECLARE #Result int
DECLARE #WorkingString1 varchar(max)
DECLARE #WorkingString2 varchar(max)
-- Add the T-SQL statements to compute the return value here
if isnull(#String1,'') = '' or isnull(#String2,'') = ''
SET #Result = 0
ELSE
BEGIN
--Convert each string to simplest form (letters
--and digits only, all upper case)
SET #WorkingString1 = dbo.SimReplaceSpecial(#String1)
SET #WorkingString2 = dbo.SimReplaceSpecial(#String2)
If RTRIM(LTRIM(#WorkingString1)) = '' Or RTRIM(LTRIM(#WorkingString2)) = ''
BEGIN
--One or both of the strings is now empty
SET #Result = 0
END
ELSE
BEGIN
If #WorkingString1 = #WorkingString2
BEGIN
--Strings are identical
SET #Result = 100
END
ELSE
BEGIN
--Find all common sub-strings
SET #Result = dbo.SimFindCommon(#WorkingString1, #WorkingString2,0)
--We now have the cumulative score. Return this
--as a percent of the maximum score. The maximum
--score is the average length of the two strings.
SET #Result = #Result * 200 / (Len(#WorkingString1) + Len(#WorkingString2))
END
END
END
-- Return the result of the function
RETURN #Result
END
--Usage--------------------------------------------------------------------
--Call the "Similar" Function only
SELECT dbo.Similar('ANDORRA WOODS','ANDORRA WOODS HEALTHCARE CENTER')
--Result = 60
SELECT dbo.Similar('ABC HEALTHCARE, JOB #31181','ABC HEALTHCARE, JOB #31251')
--Result = 85
SELECT dbo.Similar('ACTION SERVICE SALES, A SUBSIDIARY OF SINGER EQUIPMENT','ACTION SERVICE SALES, A SUBSIDIARY OF SINGER EQUIPMENT COMPANY')
--Result = 92
SELECT dbo.Similar('APEX SYSTEMS','APEX SYSTEMS, INC')
--Result = 88
SSIS/Data Tools has a Fuzzy Grouping transformation that is very helpful in situations like this. It doesn't actually group your data, rather it gives you similarity scores that you can use to determine when items should be grouped together.
Plenty of tutorials out there, here's one: The Fuzzy Grouping Transformation

Fuzzy matching on string

I have a question related to matching strings in a MSSQL database. Basically, I have a table that contains ICD9 and CPT codes. The issue is that the format that these codes come in is usually incorrect (i.e. too many characters, missing decimal, etc...). I need to be able to lookup the description for each of these codes from a lookup table containing the correct code.
Because of the way these codes are structured I can do some type of "progressive" match to at least find the category of the code.
Lets say the correct code is something like: 306.98
And for this example lets pretend there are no other values between 306 and 307.
I would like to strip the decimal and look for a match, one character at a time, until one is not found. Then select the last matching string.
So 306,3069,3098, 306981, 3069812, etc... would match the string 306.98.
I hope that makes sense to everyone. I am not sure how I would even begin to do this, so any suggestion would be a great help.
One possible solution is to strip down the code to its basic element (306) and then do a like operator:
WHERE Code LIKE '306%'
Use FLOOR function to strip the decimal part and then use a LIKE operator in the WHERE clause.
Something like:
SELECT <COLUMN-LIST>
FROM <TABLE-NAME>
WHERE <THE-COLUMN> LIKE CAST(FLOOR(306.09) AS VARCHAR) + '%'
Here you have your example.You just need to convert value to nvarchar #string.
DECLARE #string AS NVARCHAR (MAX) = '306.98';
DECLARE #Table TABLE (
TextVal NVARCHAR (MAX));
INSERT INTO #Table ([TextVal])
SELECT '4444656'
UNION ALL
SELECT '30'
UNION ALL
SELECT '3069'
UNION ALL
SELECT '306989878787'
;
WITH numbers
AS (SELECT ROW_NUMBER() OVER ( ORDER BY (SELECT 1)) AS Number
FROM [sys].[objects] AS o1 CROSS JOIN [sys].[objects] AS o2),
Chars
AS (SELECT SUBSTRING(#string, [Number], 1) AS Let,
[Number]
FROM [numbers]
WHERE [Number] <= LEN(#string)),
Joined
AS (SELECT [Let],
CAST (1 AS BIGINT) AS Number
FROM chars
WHERE [Number] = 1
UNION ALL
SELECT [J].[Let] + CASE
WHEN [Chars].[Let] = '.' THEN '' ELSE [Chars].[Let]
END AS LEt,
Chars.[Number]
FROM [Joined] AS J
INNER JOIN
[Chars]
ON [Chars].[Number] = [J].[Number] + 1)
SELECT *
FROM #Table AS T
WHERE [T].[TextVal] IN (SELECT [Let]
FROM [Joined])
OR [T].[TextVal] LIKE '%'+(SELECT TOP 1 [Let] FROM
[Joined] ORDER BY [Number] DESC ) +'%'
;
Result will be:
TextVal
30
3069
306989878787
I was able to figure it out. Basically, I just needed to step through each character of the string and look for a match until once was no longer found. Thanks for the help!
/* ICD9 Lookup */
USE TSiData_Suite_LWHS_V11
DECLARE #String NVARCHAR (10)
DECLARE #Match NVARCHAR(10)
DECLARE #Substring NVARCHAR (10)
DECLARE #Description NVARCHAR(MAX)
DECLARE #Length INT
DECLARE #Count INT
SET #String = '309.99999999'
/* Remove decimal place from string */
SET #String = REPLACE(#String,'.','')
/* Get lenth of string */
SET #Length = LEN(#String)
/* Initialize count */
SET #Count = 1
/* Get Substring */
SET #Substring = SUBSTRING(#String,1,#Count)
/* Start processing */
IF (#Length < 1 OR #String IS NULL)
/* Validate #String */
BEGIN
SET #Description = 'No match found for string. String is not proper length.'
END
ELSE IF ((SELECT COUNT(*) FROM LookupDiseases WHERE REPLACE(LookupCodeDesc,'.','') LIKE #Substring + '%') < 1)
/* Check for at least one match */
BEGIN
SET #Description = 'No match found for string.'
END
ELSE
/* Look for matching code */
BEGIN
WHILE ((SELECT COUNT(*) FROM ICD9Lookup WHERE REPLACE(LookupCodeDesc,'.','') LIKE #Substring + '%') <> 1 AND (#Count < #Length + 1))
BEGIN
/* Update substring value */
SET #Substring = SUBSTRING(#String,1,#Count + 1)
/* Increment #Count */
SET #Count += 1
/* Select the first matching code and get description */
SELECT TOP(1) #Match = LookupCodeDesc, #Description = LookupName FROM ICD9Lookup WHERE REPLACE(LookupCodeDesc,'.','') LIKE #Substring + '%' ORDER BY LookupCodeDesc ASC
END
END
PRINT #Match
PRINT #Description