How to format a numeric column as phone number in SQL - sql

I have table in the database with a phone number column. The numbers look like this:
123456789
I want to format that to look like this:
123-456-789

This should do it:
UPDATE TheTable
SET PhoneNumber = SUBSTRING(PhoneNumber, 1, 3) + '-' +
SUBSTRING(PhoneNumber, 4, 3) + '-' +
SUBSTRING(PhoneNumber, 7, 4)
Incorporated Kane's suggestion, you can compute the phone number's formatting at runtime. One possible approach would be to use scalar functions for this purpose (works in SQL Server):
CREATE FUNCTION FormatPhoneNumber(#phoneNumber VARCHAR(10))
RETURNS VARCHAR(12)
BEGIN
RETURN SUBSTRING(#phoneNumber, 1, 3) + '-' +
SUBSTRING(#phoneNumber, 4, 3) + '-' +
SUBSTRING(#phoneNumber, 7, 4)
END

I'd generally recommend you leave the formatting up to your front-end code and just return the data as-is from SQL. However, to do it in SQL, I'd recommend you create a user-defined function to format it. Something like this:
CREATE FUNCTION [dbo].[fnFormatPhoneNumber](#PhoneNo VARCHAR(20))
RETURNS VARCHAR(25)
AS
BEGIN
DECLARE #Formatted VARCHAR(25)
IF (LEN(#PhoneNo) <> 10)
SET #Formatted = #PhoneNo
ELSE
SET #Formatted = LEFT(#PhoneNo, 3) + '-' + SUBSTRING(#PhoneNo, 4, 3) + '-' + SUBSTRING(#PhoneNo, 7, 4)
RETURN #Formatted
END
GO
Which you can then use like this:
SELECT [dbo].[fnFormatPhoneNumber](PhoneNumber) AS PhoneNumber
FROM SomeTable
It has a safeguard in, in case the phone number stored isn't the expected number of digits long, is blank, null etc - it won't error.
EDIT: Just clocked on you want to update your existing data. The main bit that's relevant from my answer then is that you need to protect against "dodgy"/incomplete data (i.e. what if some existing values are only 5 characters long)

Above users mentioned, those solutions are very basic and they won't work if the database has different phone formats like:
(123)123-4564
123-456-4564
1234567989
etc
Here is a more complex solution that will work with ANY input given:
CREATE FUNCTION [dbo].[ufn_FormatPhone] (#PhoneNumber VARCHAR(32))
RETURNS VARCHAR(32)
AS
BEGIN
DECLARE #Phone CHAR(32)
SET #Phone = #PhoneNumber
-- cleanse phone number string
WHILE PATINDEX('%[^0-9]%', #PhoneNumber) > 0
SET #PhoneNumber = REPLACE(#PhoneNumber, SUBSTRING(#PhoneNumber, PATINDEX('%[^0-9]%', #PhoneNumber), 1), '')
-- skip foreign phones
IF (
SUBSTRING(#PhoneNumber, 1, 1) = '1'
OR SUBSTRING(#PhoneNumber, 1, 1) = '+'
OR SUBSTRING(#PhoneNumber, 1, 1) = '0'
)
AND LEN(#PhoneNumber) > 11
RETURN #Phone
-- build US standard phone number
SET #Phone = #PhoneNumber
SET #PhoneNumber = '(' + SUBSTRING(#PhoneNumber, 1, 3) + ') ' + SUBSTRING(#PhoneNumber, 4, 3) + '-' + SUBSTRING(#PhoneNumber, 7, 4)
IF LEN(#Phone) - 10 > 1
SET #PhoneNumber = #PhoneNumber + ' X' + SUBSTRING(#Phone, 11, LEN(#Phone) - 10)
RETURN #PhoneNumber
END

I do not recommend keeping bad data in the database and then only correcting it on the output. We have a database where phone numbers are entered in variously as :
(555) 555-5555
555+555+5555
555.555.5555
(555)555-5555
5555555555
Different people in an organization may write various retrieval functions and updates to the database, and therefore it would be harder to set in place formatting and retrieval rules. I am therefore correcting the data in the database first and foremost and then setting in place rules and form validations that protect the integrity of this database going forward.
I see no justification for keeping bad data unless as suggested a duplicate column be added with corrected formatting and the original data kept around for redundancy and reference, and YES I consider badly formatted data as BAD data.

Solutions that use SUBSTRING and concatenation + are nearly independent of RDBMS. Here is a short solution that is specific to SQL Server:
declare #x int = 123456789
select stuff(stuff(#x, 4, 0, '-'), 8, 0, '-')

You can also try this:
CREATE function [dbo].[fn_FormatPhone](#Phone varchar(30))
returns varchar(30)
As
Begin
declare #FormattedPhone varchar(30)
set #Phone = replace(#Phone, '.', '-') --alot of entries use periods instead of dashes
set #FormattedPhone =
Case
When isNumeric(#Phone) = 1 Then
case
when len(#Phone) = 10 then '('+substring(#Phone, 1, 3)+')'+ ' ' +substring(#Phone, 4, 3)+ '-' +substring(#Phone, 7, 4)
when len(#Phone) = 7 then substring(#Phone, 1, 3)+ '-' +substring(#Phone, 4, 4)
else #Phone
end
When #phone like '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9]' Then '('+substring(#Phone, 1, 3)+')'+ ' ' +substring(#Phone, 5, 3)+ '-' +substring(#Phone, 8, 4)
When #phone like '[0-9][0-9][0-9] [0-9][0-9][0-9] [0-9][0-9][0-9][0-9]' Then '('+substring(#Phone, 1, 3)+')'+ ' ' +substring(#Phone, 5, 3)+ '-' +substring(#Phone, 9, 4)
When #phone like '[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]' Then '('+substring(#Phone, 1, 3)+')'+ ' ' +substring(#Phone, 5, 3)+ '-' +substring(#Phone, 9, 4)
Else #Phone
End
return #FormattedPhone
end
use on it select
(SELECT [dbo].[fn_FormatPhone](f.coffphone)) as 'Phone'
Output will be

You Can Use FORMAT if you column is a number Syntax like
FORMAT ( value, format [, culture ] ) In use like
FORMAT ( #d, 'D', 'en-US' ) or FORMAT(123456789,'###-##-####') (But This works for only SQL SERVER 2012 And After)
In Use Like
UPDATE TABLE_NAME SET COLUMN_NAME = FORMAT(COLUMN_NAME ,'###-##-####')
And
if your column is Varchar Or Nvarchar use do like this
CONCAT(SUBSTRING(CELLPHONE,0,4),' ',SUBSTRING(CELLPHONE,4,3),' ',SUBSTRING(CELLPHONE,7,2) ,' ',SUBSTRING(CELLPHONE,9,2) )
You can always get help from
https://msdn.microsoft.com/en-us/library/hh213505.aspx

I found that this works if wanting in a (123) - 456-7890 format.
UPDATE table
SET Phone_number = '(' +
SUBSTRING(Phone_number, 1, 3)
+ ') '
+ '- ' +
SUBSTRING(Phone_number, 4, 3)
+ '-' +
SUBSTRING(Phone_number, 7, 4)

Updated #sqiller's function for my purposes
CREATE FUNCTION [toolbox].[FormatPhoneNumber] (
#PhoneNumber VARCHAR(50),
#DefaultIfUnknown VARCHAR(50)
)
RETURNS VARCHAR(50)
AS
BEGIN
-- remove any extension
IF CHARINDEX('x', #PhoneNumber, 1) > 0
SET #PhoneNumber = SUBSTRING(#PhoneNumber, 1, CHARINDEX('x', #PhoneNumber, 1) - 1)
-- cleanse phone number string
WHILE PATINDEX('%[^0-9]%',#PhoneNumber) > 0
SET #PhoneNumber = REPLACE(#PhoneNumber,
SUBSTRING(#PhoneNumber,PATINDEX('%[^0-9]%',#PhoneNumber),1),'')
-- Remove US international code if exists, i.e. 12345678900
IF SUBSTRING(#PhoneNumber,1,1) = '1' AND LEN(#PhoneNumber) = 11
SET #PhoneNumber = SUBSTRING(#PhoneNumber, 2, 10)
-- any phone numbers without 10 characters are set to default
IF LEN(#PhoneNumber) <> 10
RETURN #DefaultIfUnknown
-- build US standard phone number
SET #PhoneNumber = '(' + SUBSTRING(#PhoneNumber,1,3) + ') ' +
SUBSTRING(#PhoneNumber,4,3) + '-' + SUBSTRING(#PhoneNumber,7,4)
RETURN #PhoneNumber
END

If you want to just format the output no need to create a new table or a function. In this scenario the area code was on a separate fields. I use field1, field2 just to illustrate you can select other fields in the same query:
area phone
213 8962102
Select statement:
Select field1, field2,areacode,phone,SUBSTR(tablename.areacode,1,3) + '-' + SUBSTR(tablename.phone,1,3) + '-' + SUBSTR(tablename.areacode,4,4) as Formatted Phone from tablename
Sample OUTPUT:
columns: FIELD1, FIELD2, AREA, PHONE, FORMATTED PHONE
data: Field1, Field2, 213, 8962102, 213-896-2102

Related

How to remove last comma from csv file and add string in to it in SQL server 2012

I have csv file in SQL
#code varchar(10) = 'pc-shr,pqr,qzcx,rtde,rz-fg,kj-hl,jk_lm'
I tried
Convert(Varchar(10), #code) + CASE WHEN len(#code) >10 THEN '..etc' Else '' END [code]
but I want like this means to find last comma in a string and after that add ..etc
it should look like this
'pc-shr,pqr, ..etc'
Is this what you are looking for?
SET #code=
CASE WHEN LEN(#code) > 10
THEN SUBSTRING(#code, 0, 10) + ', etc...'
ELSE ''
END
The main problem i found that is your variable declaration i.e. #code varchar(10). It fixes its size to 10. You can try belwo :
Declare #code varchar(max) = 'pc-shr,pqr,qzcx,rtde,rz-fg,kj-hl,jk_lm';
IF LEN(#code) > 10
BEGIN
SET #code=SUBSTRING(#code, 0, 10) + ', etc...'
END
Query:
SQLFIDDLEExample
declare #code varchar(10) = 'pc-shr,pqr,qzcx,rtde,rz-fg,kj-hl,jk_lm'
select #code
--pc-shr,pqr
SELECT SUBSTRING(#code, 1, LEN(#code)-CHARINDEX (',' ,REVERSE(#code))) + '..etc'
--pc-shr..etc
Replacing right part of string where is last comma, if you want results like in your example increase size - varchar(11)
EDIT: you want this?
SELECT SUBSTRING(#code, 1, LEN(#code)-CHARINDEX (',' ,REVERSE(#code))+1) + '..etc'
--pc-shr,..etc
Last comma in a string #code varchar(10) is this pc-shr*,*pqr so I add ..etc to it
SELECT SUBSTRING(#code, 1, LEN(#code)-CHARINDEX (',' ,REVERSE(#code))+1) + '..etc '
+ SUBSTRING(#code, LEN(#code)-CHARINDEX (',' ,REVERSE(#code))+2,LEN(#code))
--pc-shr,..etc pqr

Trouble extracting First and LastName from Full Name column

I am having FullName column and I am extracting the First Name and last name using the following query
select SUBSTRING(FULL_NAME, 1, CHARINDEX(' ', FULL_NAME) - 1) AS FirstName,
SUBSTRING(FULL_NAME, CHARINDEX(' ', FULL_NAME) + 1, 500) AS LastName
from [dbo].[TABLE]
But in the Full Name column there are just First names, some 10 digit phone numbers, 4 digit extensions and some text like 'this is a special case'.
How should I modify my query to accommodate these exceptions? And also when there are only single words in the Full Name column I am getting this following error message:
"Invalid length parameter passed to the LEFT or SUBSTRING function."
Parsing good names from free form fields is not an easy task...
I would suggest a dual approach.
Identify common patterns, i.e. you might find phone number with something like this
Where IsNumeric( Replace(Field,'-','')=1
and you might identify single names with
Where charindex(' ',trim(field))=0
etc.
Once you've identified them, the write code to attempt to split them...
So you might use the code you have above with the following WHERE clause
select SUBSTRING(FULL_NAME, 1, CHARINDEX(' ', FULL_NAME) - 1) AS FirstName,
SUBSTRING(PRQ_BP_CONTACT_NAME, CHARINDEX(' ', FULL_NAME) + 1, 500)
AS LastN
from [dbo].[TABLE]
where charindex(' ',trim(field))>0 and Where IsNumeric( Replace(Field,'-','')=0
Use the WHERE clauses to (a) make sure you only get records you can parse and (b) help identify the oddball cases you'll like need to do by hand...
Good luck
You could go with a function this allows you to put in any logic you need in the transform and keep things a bit more readable :
create function dbo.namepart( #fullname varchar(50), #part varchar(5))
returns varchar(10)
as
begin
declare #first varchar(50)
declare #last varchar(50)
declare #sp int
if #fullname like '%special value%' return ''
if #fullname like '% %'
begin
set #sp = CHARINDEX(' ', #fullname)
set #first = left(#fullname, #sp - 1)
set #last = substring(#fullname,#sp + 1 ,50)
if isnumeric(#last) <> 0 set #last = ''
end
else
begin
set #first = #fullname
set #last = ''
end
if #part like 'f%'
return #first
else
return #last
return ''
end
Sample data
create table blah(
full_name varchar(50)
)
insert into blah values ( 'john smith' ), ('paul 12345'),('evan'),('special value')
And see if it works
select
dbo.namepart(full_name,'first') first,
dbo.namepart(full_name,'last') last,
full_name
from blah
http://sqlfiddle.com/#!6/eb28f/2

How to get the nth string in any generic word or sentence with a space delimiter

How do I get the nth word in a sentence or a set of strings with space delimiter?
Sorry for the change in the requirement.Thank you.
By using instr.
select substr(help, 1, instr(help,' ') - 1)
from ( select 'hello my name is...' as help
from dual )
instr(help,' ') returns the positional index of the first occurrence of the second argument in the first, inclusive of the string you're searching for. i.e. the first occurrence of ' ' in the string 'hello my name is...' plus the space.
substr(help, 1, instr(help,' ') - 1) then takes the input string from the first character to the index indicated in instr(.... I then remove one so that the space isn't included..
For the nth occurrence just change this slightly:
instr(help,' ',1,n) is the nth occurrence of ' ' from the first character. You then need to find the positional index of the next index instr(help,' ',1,n + 1), lastly work out the difference between them so you know how far to go in your substr(.... As you're looking for the nth, when n is 1 this breaks down and you have to deal with it, like so:
select substr( help
, decode( n
, 1, 1
, instr(help, ' ', 1, n - 1) + 1
)
, decode( &1
, 1, instr(help, ' ', 1, n ) - 1
, instr(help, ' ', 1, n) - instr(help, ' ', 1, n - 1) - 1
)
)
from ( select 'hello my name is...' as help
from dual )
This will also break down at n. As you can see this is getting ridiculous so you might want to consider using regular expressions
select regexp_substr(help, '[^[:space:]]+', 1, n )
from ( select 'hello my name is...' as help
from dual )
Try this. An example of getting the 4th word:
select names from (
select
regexp_substr('I want my two dollars','[^ ]+', 1, level) as names,
rownum as nth
from dual
connect by regexp_substr('I want my two dollars', '[^ ]+', 1, level) is not null
)
where nth = 4;
The inner query is converting the space-delimited string into a set of rows. The outer query is grabbing the nth item from the set.
Try something like
WITH q AS (SELECT 'ABCD EFGH IJKL' AS A_STRING FROM DUAL)
SELECT SUBSTR(A_STRING, 1, INSTR(A_STRING, ' ')-1)
FROM q
Share and enjoy.
And here's the solution for the revised question:
WITH q AS (SELECT 'ABCD EFGH IJKL' AS A_STRING, 3 AS OCCURRENCE FROM DUAL)
SELECT SUBSTR(A_STRING,
CASE
WHEN OCCURRENCE=1 THEN 1
ELSE INSTR(A_STRING, ' ', 1, OCCURRENCE-1)+1
END,
CASE
WHEN INSTR(A_STRING, ' ', 1, OCCURRENCE) = 0 THEN LENGTH(A_STRING)
ELSE INSTR(A_STRING, ' ', 1, OCCURRENCE) - CASE
WHEN OCCURRENCE=1 THEN 0
ELSE INSTR(A_STRING, ' ', 1, OCCURRENCE-1)
END - 1
END)
FROM q;
Share and enjoy.
CREATE PROC spGetCharactersInAStrings
(
#S VARCHAR(100) = '^1402 WSN NI^AMLAB^tev^e^^rtS htimS 0055518',
#Char VARCHAR(100) = '8'
)
AS
-- exec spGetCharactersInAStrings '^1402 WSN NI^AMLAB^tev^e^^rtS htimS 0055518', '5'
BEGIN
DECLARE #i INT = 1,
#c INT,
#pos INT = 0,
#NewStr VARCHAR(100),
#sql NVARCHAR(100),
#ParmDefinition nvarchar(500) = N'#retvalOUT int OUTPUT'
DECLARE #D TABLE
(
ID INT IDENTITY(1, 1),
String VARCHAR(100),
Position INT
)
SELECT #c = LEN(#S), #NewStr = #S
WHILE #i <= #c
BEGIN
SET #sql = ''
SET #sql = ' SELECT #retvalOUT = CHARINDEX(''' + + #Char + ''',''' + #NewStr + ''')'
EXEC sp_executesql #sql, #ParmDefinition, #retvalOUT=#i OUTPUT;
IF #i > 0
BEGIN
set #pos = #pos + #i
SELECT #NewStr = SUBSTRING(#NewStr, #i + 1, LEN(#S))
--SELECT #NewStr '#NewStr', #Char '#Char', #pos '#pos', #sql '#sql'
--SELECT #NewStr '#NewStr', #pos '#pos'
INSERT INTO #D
SELECT #NewStr, #pos
SET #i = #i + 1
END
ELSE
BREAK
END
SELECT * FROM #D
END
If you're using MySQL and cannot use the instr function that accepts four parameters or regexp_substr, you can do this way:
select substring_index(substring_index(help, ' ', 2), ' ', -1)
from (select 'hello my name is...' as help) h
Result: "my".
Replace "2" in the code above with the number of the word you want.
If you are using SQL Server 2016+ then you can take advantage of the STRING_SPLIT function. It returns rows of string values and if you aim to get nth value, then you can use Row_Number() window function.
Here there is a little trick as you don't want to really order by something so that you have to "cheat" the row_number function and allow its value in the natural order which is the STRING_SPLIT() function will spit out.
Below is a code snippet if you want to find the third word of the string
Declare #_intPart INT = 3; -- change nth work here, start # from 1 not 0
SELECT value FROM(
SELECT value,
ROW_NUMBER()OVER(ORDER BY (SELECT 1)) AS rowno
FROM STRING_SPLIT('hello world this is amazing', ' ')
) AS o1 WHERE o1.rowno = #_intPart;
You can also make a scalar function to retrieve values.

Using PATINDEX to find varying length patterns in T-SQL

I'm looking to pull floats out of some varchars, using PATINDEX() to spot them. I know in each varchar string, I'm only interested in the first float that exists, but they might have different lengths.
e.g.
'some text 456.09 other text'
'even more text 98273.453 la la la'
I would normally match these with a regex
"[0-9]+[.][0-9]+"
However, I can't find an equivalent for the + operator, which PATINDEX accepts. So they would need to be matched (respectively) with:
'[0-9][0-9][0-9].[0-9][0-9]' and '[0-9][0-9][0-9][0-9][0-9].[0-9][0-9][0-9]'
Is there any way to match both of these example varchars with one single valid PATINDEX pattern?
I blogged about this a while ago.
Extracting numbers with SQL server
Declare #Temp Table(Data VarChar(100))
Insert Into #Temp Values('some text 456.09 other text')
Insert Into #Temp Values('even more text 98273.453 la la la')
Insert Into #Temp Values('There are no numbers in this one')
Select Left(
SubString(Data, PatIndex('%[0-9.-]%', Data), 8000),
PatIndex('%[^0-9.-]%', SubString(Data, PatIndex('%[0-9.-]%', Data), 8000) + 'X')-1)
From #Temp
Wildcards.
SELECT PATINDEX('%[0-9]%[0-9].[0-9]%[0-9]%','some text 456.09 other text')
SELECT PATINDEX('%[0-9]%[0-9].[0-9]%[0-9]%','even more text 98273.453 la la la')
Yes you need to link to the clr to get regex support. But if PATINDEX does not do what you need then regex was designed exactly for that.
http://msdn.microsoft.com/en-us/magazine/cc163473.aspx
Should be checked for robustness (what if you only have an int, for example), but this is just to put you on a track:
if exists (select routine_name from information_schema.routines where routine_name = 'GetFirstFloat')
drop function GetFirstFloat
go
create function GetFirstFloat (#string varchar(max))
returns float
as
begin
declare #float varchar(max)
declare #pos int
select #pos = patindex('%[0-9]%', #string)
select #float = ''
while isnumeric(substring(#string, #pos, 1)) = 1
begin
select #float = #float + substring(#string, #pos, 1)
select #pos = #pos + 1
end
return cast(#float as float)
end
go
select dbo.GetFirstFloat('this is a string containing pi 3.14159216 and another non float 3 followed by a new fload 5.41 and that''s it')
select dbo.GetFirstFloat('this is a string with no float')
select dbo.GetFirstFloat('this is another string with an int 3')
Given that the pattern is going to be varied in length, you're not going to have a rough time getting this to work with PATINDEX. There is another post that I wrote, which I've modified to accomplish what you're trying to do here. Will this work for you?
CREATE TABLE #nums (n INT)
DECLARE #i INT
SET #i = 1
WHILE #i < 8000
BEGIN
INSERT #nums VALUES(#i)
SET #i = #i + 1
END
CREATE TABLE #tmp (
id INT IDENTITY(1,1) not null,
words VARCHAR(MAX) null
)
INSERT INTO #tmp
VALUES('I''m looking for a number, regardless of length, even 23.258 long'),('Maybe even pi which roughly 3.14159265358,'),('or possibly something else that isn''t a number')
UPDATE #tmp SET words = REPLACE(words, ',',' ')
;WITH CTE AS (SELECT ROW_NUMBER() OVER (ORDER BY ID) AS rownum, ID, NULLIF(SUBSTRING(' ' + words + ' ' , n , CHARINDEX(' ' , ' ' + words + ' ' , n) - n) , '') AS word
FROM #nums, #tmp
WHERE ID <= LEN(' ' + words + ' ') AND SUBSTRING(' ' + words + ' ' , n - 1, 1) = ' '
AND CHARINDEX(' ' , ' ' + words + ' ' , n) - n > 0),
ids AS (SELECT ID, MIN(rownum) AS rownum FROM CTE WHERE ISNUMERIC(word) = 1 GROUP BY id)
SELECT CTE.rownum, cte.id, cte.word
FROM CTE, ids WHERE cte.id = ids.id AND cte.rownum = ids.rownum
The explanation and origin of the code is covered in more detail in the origional post
PATINDEX is not powerful enough to do that. You should use regular expressions.
SQL Server has Regular expression support since SQL Server 2005.

Sql concatenate problem?

In my table i have a column called Dep_user_code which is nothing but employeeid...Everytime I need to increment the employeeid when i insert a new value..but it has both alphabet and number..i need to increment the number alone.. for example if my employeeid is 'NECUSER0001' means next time when i insert a new employeeid it has to be 'NECUSER0002' dynamically i have to generate like this..everytime when i insert a value it has to increment..
I have tried like taking the string part and number part like this but dont know how to implement this...Any suggestion?
select SUBSTRING(Dep_user_code,1,7) from NEC_Customer_User_Map
select SUBSTRING(Dep_user_code,8,4) from NEC_Customer_User_Map
you should also keep an identity key. use SELECT IDENT_CURRENT('NEC_Customer_User_Map') to find out last inserted ID.
If the value is always text then numbers, you split apart the value using Patindex:
Select Substring( Dep_user_code, 1, PatIndex( '%[0-9]%', Dep_user_code) - 1 ) As TextPortion
, Substring( Dep_user_code, PatIndex( '%[0-9]%', Dep_user_code)
, Len(Dep_user_code) ) As NumberPortion
However, whether you can use an identity in combination with a prefix depends on whether you can allow gaps. If you cannot allow gaps, then you need to query for the next id value that you can use which can be done in a variety of ways depending on the needs.
I've had to support databases with setups like this before and while I'm generally not a fan of this style, I'm assuming you have some reason for not storing the NECUSER in one column and the incrementing identity integer in another column with the PK set to both. If not, I'd suggest going that route and letting SQL do the work for you.
Otherwise, using the result of the following query should yield the results you want. I've added comments to try and answer any questions the query might raise.
SELECT SUBSTRING(Dep_user_code, 1, 7) +
RIGHT(
REPLICATE('0', 3) + --Ensure we have padding 0s
IsNull(MAX(CAST(SUBSTRING(Dep_user_code, 8, 4) AS INT), -1) + 1 --Work with ints, find MAX or set NULL to -1 so +1 will = 0
, 4) --Only want 4 character total from RIGHT function
FROM NEC_Customer_User_Map
WITH last AS (
SELECT MAX(Dep_user_code) AS Code
FROM NEC_Customer_User_Map
WHERE LEFT(Dep_user_code, 7) = 'NECUSER'
)
SELECT LEFT(Dep_user_code, 7) + RIGHT(CAST(STUFF(Code, 1, 7, '1') AS int) + 1, 4)
FROM last
The RIGHT part does the following:
replaces 'NECUSER' with '1' thus getting something like '10002';
casts the result as int;
increments by 1;
(implicitly) casts the value to varchar and gets the last 4 chars.
Maybe STUFF(Code, 1, 7, '1') should better be replaced with '1' + RIGHT(Code, 4), not sure.
EDIT: As it happens, the implicit conversion could also be employed in case of converting the string to the integer too:
... + RIGHT(STUFF(Code, 1, 7, '1') + 1, 4) ...
or
... + RIGHT('1' + RIGHT(Code, 4) + 1, 4) ...
declare #max varchar(20)
declare #number varchar(20)
select #max = max(cast(substring(dep_user_name , 8, 4) as int)) from NEC_Customer_User_Map (nolock)
select #max = isnull(#max, 0) + 1
select #max = (case when len(#max) = 1 then '000' + #max
when len(#max) = 2 then '00' + #max
when len(#max) = 3 then '0' + #max
else #max
end)
Select #number = (Substring( dep_user_name, 1, PatIndex( '%[0-9]%', dep_user_name) - 1 ) + #max) from NEC_Customer_User_Map
insert into NEC_Customer_User_Map(Dep_User_Name) values (#number )
You can consider to have both parts of Dep_user_code as separate fileds in your db in order to take advantage of several tsql features like IDENTITY and IDENT_CURRENT()