Increment by on substring -SQL - sql

I have a list of strings like so:
M308_7
M308_8
M308_9
M308_10
and want to grab the MAX number from the last digits after the "_" of the string and increment this number by one (so the number it should return is 11)
I read on other posts to convert the last digits to integers as 9 is higher than 10 in alphabetical and that was the reason for it returning _9 as the MAX.
I have done this but still the value being returned is 9 when it should be 10
See below what I have so far..
select
#BomNo = MAX(case when CHARINDEX('_',HeaderNo.No_)>0 then
CAST(SUBSTRING(HeaderNo.No_, 6, len(CHARINDEX('_',HeaderNo.No_))) AS INT)else 0 end)
--MAX(case when CHARINDEX('_',NavBomHeader.No_)>0 then CAST(SUBSTRING(HeaderNo.No_,CHARINDEX('_',HeaderNo.No_)+1,len(CHARINDEX('_',HeaderNo.No_))) AS INT) else 0 end)+1
from nameoftable as HeaderNo
where SUBSTRING(HeaderNo.No_, 1, case when CHARINDEX('_',HeaderNo.No_)>0 then CHARINDEX('_',HeaderNo.No_)-1 else len(HeaderNo.No_) end) ='M308'

Another implementation.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (id INT IDENTITY PRIMARY KEY, No_ VARCHAR(30));
INSERT INTO #tbl (No_) VALUES
('M308_7'),
('M308_8'),
('M308_9'),
('M308_10');
-- DDL and sample data population, end
SELECT NextNo = MAX(TRY_CAST(RIGHT(No_, LEN(No_) - pos) AS INT)) + 1
FROM #tbl
CROSS APPLY (SELECT CHARINDEX('_', No_)) AS t(pos);
Output
+--------+
| NextNo |
+--------+
| 11 |
+--------+

You probably have a design flaw in your database. I suspect that you should be using an identity column.
In any case, the answer to your question is logic like this:
select concat('M308_', max(try_convert(int, stuff(no_, 1, charindex('_', no_), ''))) + 1)
from (values ('M308_7'), ('M308_8'), ('M308_9'), ('M308_10')) v(no_);
Here is a db<>fiddle.

Related

SQL Script to find Count the number of :username Occurrences of a String

I have a table that stores information whenever user make changes to the DB. I want to extract how many times the user make changes on the date on the application. The info is normally stored for each user in one row for example :
2019-06-15randomname1:YES I DID IT 2019-06-14randomname2:HHHHHHH JJJJJJ 2019-06-14Urandomnamexxxxxx: COMMENT OF PEOPLE
What I want is to search :username to detect how many times the user has changed. In this instance. The answer suppose to be 3. How can I do it
DECLARE #logEntry VARCHAR(4000);
SET #logEntry = ':' + (SELECT PERSON_NAME FROM P_PERSON WHERE PERSON = logged_person)
SELECT
id
,value
,COUNT = (LEN(value) - LEN(REPLACE(value, #logEntry , '')))/LEN(#logEntry)
FROM table
Will I use regular expression because for this particular example the answer will be 3 since we have 3.
I have decided to use :username I am having problem with Subquery returned more than 1 value :
If I understand, you want to count the occurrence of a date in a string
DECLARE #D VARCHAR(10) = '2019-01-01';
SELECT *, LEN(V) - (LEN(REPLACE(V, #D, '')) * 10) Occurrence
FROM (VALUES('A2019-01-01B2019-01-01C2019-01-01D2019-01-01E2019-01-01F2019-01-01'))T(V);
Returns:
+--------------------------------------------------------------------+------------+
| V | Occurrence |
+--------------------------------------------------------------------+------------+
| A2019-01-01B2019-01-01C2019-01-01D2019-01-01E2019-01-01F2019-01-01 | 6 |
+--------------------------------------------------------------------+------------+
Note that this will works only when the string doesn't contains a white spaces.
If you have a white spaces, then you need to remove them first as
DECLARE #D VARCHAR(10) = '2019-01-01';
SELECT *, LEN(REPLACE(V, ' ', '')) - (LEN(REPLACE(REPLACE(V, ' ', ''), #D, '')) * 10) Occurrence
FROM (VALUES('A 2019-01-01 B 2019-01-01 C 2019-01-01 D 2019-01-01 E 2019-01-01 F 2019-01-01'))T(V);
You just changed your question, to search by a user name, but since the ':' is fixed, and if you have 2016+ version you can do as
DECLARE #D VARCHAR(10) = 'UserName1';
SELECT *,
(SELECT COUNT(1) FROM STRING_SPLIT(V, ':') WHERE Value LIKE CONCAT('%', #D, '%'))
FROM (VALUES
('2019-06-15UserName1:YES I DID IT 2019-06-14UserName2:HHHHHHH JJJJJJ 2019-06-14UserName1: COMMENT OF PEOPLE')
) T(V);
Finally, I'll recommend to re-think of that design, which is the real issue here, and read more about normalization.
UPDATE:
Here is how to count the user name with joining the two tables
SELECT *,
(
SELECT COUNT(1)
FROM STRING_SPLIT(Col, ':')
WHERE Value LIKE CONCAT('%', UserName)
) Cnt
FROM Users U JOIN Data D
ON D.Col LIKE CONCAT('%', U.UserName, '%');
Returns:
+----------+----------------------------------------------+-----+
| UserName | Col | Cnt |
+----------+----------------------------------------------+-----+
| User1 | 2019-01-01User1:YES 2019-01-02User2:No | 1 |
| User2 | 2019-01-01User1:YES 2019-01-02User2:No | 1 |
| User1 | 2019-01-01User1:YES I 2019-01-02User1:No Way | 2 |
+----------+----------------------------------------------+-----+
See how it's working on live demo
First, you have a lousy data model and processing. You should not be just adding substrings to a string. You should be adding new rows to a table. And, you should not be encoding information in a string. You should be using columns for that.
My strongest suggestion is that you fix your data model and processing.
That said, you might be stuck with this situation. THe simplest solution is just to look for
SELECT id, value,
(LEN(REPLACE(value, 'XXXXXXXXXXXXX:', 'XXXXXXXXXXXXX:1') -
LEN(value)
) as Num_Times
FROM Table;
Of course, this assumes that 'XXXXXXXXXXXXX:' doesn't actually occur in the message. If that is a possibility, see my original comment on the data structure.
The following will do as you ask, but you seriously need to reconsider how you store your data. What if instead of someone commenting "I did it", they entered "I did it on 2019-01-01"?
-- DateCount
-- Return number of occurances of ####-##-## where # is a digit
create function dbo.DateCount(#s nvarchar(max))
returns int as
begin
declare #k int = 0 -- #k holds the count so far
declare #i int = 1 -- index into string, start at first character
while #i < len(#s)-9 -- keep checking until we get to the end
begin
if substring(#s,#i,10) like '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
set #k = #k + 1 -- increment count if these 10 characters match
set #i = #i + 1 -- check the next character
end
return #k -- return the count
end
go
select dbo.DateCount( '2019-06-15randomname1:YES I DID IT 2019-06-14random'
+ 'name2:HHHHHHH JJJJJJ 2019-06-14Urandomnamexxxxxx: '
+ 'COMMENT OF PEOPLE' )
-- Result is 3
If you're keen on using a set-based solution instead of a while loop, you can try this:
create function dbo.DateCount(#s nvarchar(max))
returns int as
begin
declare #k int;
with A as ( select 1 as I
union all
select I+1 as I from A where I<=len(#s)-9 )
select #k=count(*) from A
where substring(#S,I,10) like '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
option (maxrecursion 0)
return #k
end
But, in my performance tests, I find that the set-based solution takes 50% longer.

Take a value from an SQL table cell and insert it in another cell

I have an old SQL database (Microsoft's SQL Server) with thousands of rows that contains data as follows:
ID urlString
1 page.aspx?pageID=34
2 page.aspx?pageID=163
3 page.aspx
4 page.aspx?pageID=23
I've added a new column (pageID) to the database. I want to create an UPDATE query to copy the pageID from the URLstring and insert it in the new column (pageID) as follows. If there is no pageID I want to add 0. How can I accomplish that?
ID URLstring pageID
1 page.aspx?pageID=34 34
2 page.aspx?pageID=163 163
3 page.aspx 0
4 page.aspx?pageID=23 23
UPDATE YourTable
SET pageID=
SUBSTRING(urlString,CHARINDEX('=', urlString)+1,CHARINDEX('=', urlString))
To have the 0 value
UPDATE YourTable
SET pageID=
CASE
WHEN CHARINDEX('=', urlString) > 0 THEN
SUBSTRING(urlString,CHARINDEX('=', urlString)+1,CHARINDEX('=', urlString))
ELSE 0
END
please try the following
SELECT urlString, cast(REVERSE(SUBSTRING(REVERSE(urlString),0,CHARINDEX('=',REVERSE(urlString)))) as smallint) AS [pageID]
Hope this helps.
Well, whichever SQL language variant the database uses will make a difference here. (i.e. SQLplus, NOSQL, etc.) However, it shouldn't be toooooooooo complicated. Assuming that both columns are INTs, you could probably just do something like so
UPDATE table_name
SET pageID = URLstring;
Here is some other sources for additional information.
A similar stack overflow question:
Copy data from one column to other column (which is in a different table)
This is a TutorialsPoint webpage on the matter: http://www.tutorialspoint.com/sql/sql-update-query.htm (TutorialsPoint is usually one of my first stops for any programming-related knowledge, it's quite a valuable website.)
This is a w3schools webpage on the matter: http://www.w3schools.com/sql/sql_update.asp
Hope you get everything figured out!
You can achieve this by the PARSENAME using the following UPDATE query:
UPDATE TestTable
SET pageID = CASE WHEN ISNUMERIC(PARSENAME(REPLACE(URLstring, '=', '.'), 1)) = 1 THEN PARSENAME(REPLACE(URLstring, '=', '.'), 1)
ELSE 0 END
Sample execution with the given sample data
DECLARE #TestTable TABLE (ID INT, URLstring VARCHAR (200), PageID INT);
INSERT INTO #TestTable (ID, URLstring, pageID) VALUES
(1, 'page.aspx?pageID=34' , NULL ),
(2, 'page.aspx?pageID=163' , NULL ),
(3, 'page.aspx' , NULL ),
(4, 'page.aspx?pageID=23' , NULL );
UPDATE #TestTable
SET pageID = CASE WHEN ISNUMERIC(PARSENAME(REPLACE(URLstring, '=', '.'), 1)) = 1 THEN PARSENAME(REPLACE(URLstring, '=', '.'), 1)
ELSE 0 END
So the SELECT * FROM #TestTable will result as:
ID URLstring PageID
------------------------------------
1 page.aspx?pageID=34 34
2 page.aspx?pageID=163 163
3 page.aspx 0
4 page.aspx?pageID=23 23
I try it:
update yourtable
set pageID=
case when
substring(URLstring, charindex('=', URLstring) +1, len(URLstring) - charindex('=', URLstring) )
=URLstring then '0'
else
substring(URLstring, charindex('=', URLstring) +1, len(URLstring) - charindex('=', URLstring) )
end
Using CASE, PATINDEX and SUBSTRING it's fairly easy to extract the page id from the url.
Create and populate sample table (Please save us this step in your future questions)
DECLARE #T As TABLE
(
Id int IDENTITY(1,1),
URLString varchar (40),
PageId int
)
INSERT INTO #T (URLString) VALUES
('page.aspx?blabla=yadayada&pageID=34'),
('page.aspx?pageID=163'),
('page.aspx'),
('page.aspx?pageID=23')
Update statement:
UPDATE #T
SET PageId = CAST(
CASE WHEN PATINDEX('%pageID=%', URLString) > 0 THEN
SUBSTRING(URLString, PATINDEX('%pageID=%', URLString) + 7, LEN(URLString))
ELSE
'0'
END
As int)
Verification:
SELECT Id, URLString, PageId
FROM #T
Results:
Id URLString PageId
----------- ---------------------------------------- -----------
1 page.aspx?blabla=yadayada&pageID=34 34
2 page.aspx?pageID=163 163
3 page.aspx 0
4 page.aspx?pageID=23 23

Finding strings with duplicate letters inside

Can somebody help me with this little task? What I need is a stored procedure that can find duplicate letters (in a row) in a string from a table "a" and after that make a new table "b" with just the id of the string that has a duplicate letter.
Something like this:
Table A
ID Name
1 Matt
2 Daave
3 Toom
4 Mike
5 Eddie
And from that table I can see that Daave, Toom, Eddie have duplicate letters in a row and I would like to make a new table and list their ID's only. Something like:
Table B
ID
2
3
5
Only 2,3,5 because that is the ID of the string that has duplicate letters in their names.
I hope this is understandable and would be very grateful for any help.
In your answer with stored procedure, you have 2 mistakes, one is missing space between column name and LIKE clause, second is missing single quotes around search parameter.
I first create user-defined scalar function which return 1 if string contains duplicate letters:
EDITED
CREATE FUNCTION FindDuplicateLetters
(
#String NVARCHAR(50)
)
RETURNS BIT
AS
BEGIN
DECLARE #Result BIT = 0
DECLARE #Counter INT = 1
WHILE (#Counter <= LEN(#String) - 1)
BEGIN
IF(ASCII((SELECT SUBSTRING(#String, #Counter, 1))) = ASCII((SELECT SUBSTRING(#String, #Counter + 1, 1))))
BEGIN
SET #Result = 1
BREAK
END
SET #Counter = #Counter + 1
END
RETURN #Result
END
GO
After function was created, just call it from simple SELECT query like following:
SELECT
*
FROM
(SELECT
*,
dbo.FindDuplicateLetters(ColumnName) AS Duplicates
FROM TableName) AS a
WHERE a.Duplicates = 1
With this combination, you will get just rows that has duplicate letters.
In any version of SQL, you can do this with a brute force approach:
select *
from t
where t.name like '%aa%' or
t.name like '%bb%' or
. . .
t.name like '%zz%'
If you have a case sensitive collation, then use:
where lower(t.name) like '%aa%' or
. . .
Here's one way.
First create a table of numbers
CREATE TABLE dbo.Numbers
(
number INT PRIMARY KEY
);
INSERT INTO dbo.Numbers
SELECT number
FROM master..spt_values
WHERE type = 'P'
AND number > 0;
Then with that in place you can use
SELECT *
FROM TableA
WHERE EXISTS (SELECT *
FROM dbo.Numbers
WHERE number < LEN(Name)
AND SUBSTRING(Name, number, 1) = SUBSTRING(Name, number + 1, 1))
Though this is an old post it's worth posting a solution that will be faster than a brute force approach or one that uses a scalar udf (which generally drag down performance). Using NGrams8K this is rather simple.
--sample data
declare #table table (id int identity primary key, [name] varchar(20));
insert #table([name]) values ('Mattaa'),('Daave'),('Toom'),('Mike'),('Eddie');
-- solution #1
select id
from #table
cross apply dbo.NGrams8k([name],1)
where charindex(replicate(token,2), [name]) > 0
group by id;
-- solution #2 (SQL 2012+ solution using LAG)
select id
from
(
select id, token, prevToken = lag(token,1) over (partition by id order by position)
from #table
cross apply dbo.NGrams8k([name],1)
) prep
where token = prevToken
group by id; -- optional id you want to remove possible duplicates.
another burte force way:
select *
from t
where t.name ~ '(.)\1';

Remove a sentence from a paragraph that has a specific pattern with T-SQL

I have a large number of descriptions that can be anywhere from 5 to 20 sentences each. I am trying to put a script together that will locate and remove a sentence that contains a word with numbers before or after it.
before example: Hello world. Todays department has 345 employees. Have a good day.
after example: Hello world. Have a good day.
My main problem right now is identifying the violation.
Here "345 employees" is what causes the sentence to be removed. However, each description will have a different number and possibly a different variation of the word employee.
I would like to avoid having to create a table of all the different variations of employee.
JTB
This would make a good SQL Puzzle.
Disclaimer: there are probably TONS of edge cases that would blow this up
This would take a string, split it out into a table with a row for each sentence, then remove the rows that matched a condition, and then finally join them all back into a string.
CREATE FUNCTION dbo.fn_SplitRemoveJoin(#Val VARCHAR(2000), #FilterCond VARCHAR(100))
RETURNS VARCHAR(2000)
AS
BEGIN
DECLARE #tbl TABLE (rid INT IDENTITY(1,1), val VARCHAR(2000))
DECLARE #t VARCHAR(2000)
-- Split into table #tbl
WHILE CHARINDEX('.',#Val) > 0
BEGIN
SET #t = LEFT(#Val, CHARINDEX('.', #Val))
INSERT #tbl (val) VALUES (#t)
SET #Val = RIGHT(#Val, LEN(#Val) - LEN(#t))
END
IF (LEN(#Val) > 0)
INSERT #tbl VALUES (#Val)
-- Filter out condition
DELETE FROM #tbl WHERE val LIKE #FilterCond
-- Join back into 1 string
DECLARE #i INT, #rv VARCHAR(2000)
SET #i = 1
WHILE #i <= (SELECT MAX(rid) FROM #tbl)
BEGIN
SELECT #rv = IsNull(#rv,'') + IsNull(val,'') FROM #tbl WHERE rid = #i
SET #i = #i + 1
END
RETURN #rv
END
go
CREATE TABLE #TMP (rid INT IDENTITY(1,1), sentence VARCHAR(2000))
INSERT #tmp (sentence) VALUES ('Hello world. Todays department has 345 employees. Have a good day.')
INSERT #tmp (sentence) VALUES ('Hello world. Todays department has 15 emps. Have a good day. Oh and by the way there are 12 employees somewhere else')
SELECT
rid, sentence, dbo.fn_SplitRemoveJoin(sentence, '%[0-9] Emp%')
FROM #tmp t
returns
rid | sentence | |
1 | Hello world. Todays department has 345 employees. Have a good day. | Hello world. Have a good day.|
2 | Hello world. Todays department has 15 emps. Have a good day. Oh and by the way there are 12 employees somewhere else | Hello world. Have a good day. |
I've used the split/remove/join technique as well.
The main points are:
This uses a pair of recursive CTEs, rather than a UDF.
This will work with all English sentence endings: . or ! or ?
This removes whitespace to make the comparison for "digit then employee" so you don't have to worry about multiple spaces and such.
Here's the SqlFiddle demo, and the code:
-- Split descriptions into sentences (could use period, exclamation point, or question mark)
-- Delete any sentences that, without whitespace, are like '%[0-9]employ%'
-- Join sentences back into descriptions
;with Splitter as (
select ID
, ltrim(rtrim(Data)) as Data
, cast(null as varchar(max)) as Sentence
, 0 as SentenceNumber
from Descriptions -- Your table here
union all
select ID
, case when Data like '%[.!?]%' then right(Data, len(Data) - patindex('%[.!?]%', Data)) else null end
, case when Data like '%[.!?]%' then left(Data, patindex('%[.!?]%', Data)) else Data end
, SentenceNumber + 1
from Splitter
where Data is not null
), Joiner as (
select ID
, cast('' as varchar(max)) as Data
, 0 as SentenceNumber
from Splitter
group by ID
union all
select j.ID
, j.Data +
-- Don't want "digit+employ" sentences, remove whitespace to search
case when replace(replace(replace(replace(s.Sentence, char(9), ''), char(10), ''), char(13), ''), char(32), '') like '%[0-9]employ%' then '' else s.Sentence end
, s.SentenceNumber
from Joiner j
join Splitter s on j.ID = s.ID and s.SentenceNumber = j.SentenceNumber + 1
)
-- Final Select
select a.ID, a.Data
from Joiner a
join (
-- Only get max SentenceNumber
select ID, max(SentenceNumber) as SentenceNumber
from Joiner
group by ID
) b on a.ID = b.ID and a.SentenceNumber = b.SentenceNumber
order by a.ID, a.SentenceNumber
One way to do this. Please note that it only works if you have one number in all sentences.
declare #d VARCHAR(1000) = 'Hello world. Todays department has 345 employees. Have a good day.'
declare #dr VARCHAR(1000)
set #dr = REVERSE(#d)
SELECT REVERSE(RIGHT(#dr,LEN(#dr) - CHARINDEX('.',#dr,PATINDEX('%[0-9]%',#dr))))
+ RIGHT(#d,LEN(#d) - CHARINDEX('.',#d,PATINDEX('%[0-9]%',#d)) + 1)

SQL code to generate next sequence in a alphanumeric string

I have some string values already populated in a nvarchar column. the format of the strings are like this:
For example: 16B, 23G, 128F, 128M etc...
I need to find out the maximum value from these, then generate the next one from code. The logic for picking up the maximum item is like the following:
Pick up the string with the largest number.
If multiple largest number, then pick up the string the largest alphabet among those.
For example, the largest string from the above series is 128M.
Now I need to generate the next sequence. the next string will have
The same number as the largest one, but alphabet incremented by 1. I.E. 128N
If the alphabet reaches to Z, then the number gets incremented by 1, and alphabet is A.
for example, the next String of 128Z is 129A.
Can anyone let me know what kind of SQL can get me the desired string.
If you can change the table definition(*), keeping the basic values entirely numeric and just formatting into these strings would be easier:
create table T (
CoreValue int not null,
DisplayValue as CONVERT(varchar(10),(CoreValue / 26)+1) + CHAR(ASCII('A') + (CoreValue-1) % 26)
)
go
insert into T (CoreValue)
select ROW_NUMBER() OVER (ORDER BY so1.object_id)
from sys.objects so1,sys.objects so2
go
select * from T
Results:
CoreValue DisplayValue
----------- ------------
1 1A
2 1B
3 1C
4 1D
5 1E
6 1F
....
22 1V
23 1W
24 1X
25 1Y
26 2Z
27 2A
28 2B
29 2C
....
9593 369Y
9594 370Z
9595 370A
9596 370B
9597 370C
9598 370D
9599 370E
9600 370F
9601 370G
9602 370H
9603 370I
9604 370J
So inserting a new value is as simple as taking the MAX from the column and adding 1 (assuming serializable isolation or similar, to deal with multiple users)
(*) Even if you can't change your table definition - I'd still generate this table. You can then join it to the original table and can use it to perform a simple MAX against an int column, then add one and look up the next alphanumeric value to be used. Just populate it with as many values as you ever expect to use.
Assuming:
CREATE TABLE MyTable
([Value] varchar(4))
;
INSERT INTO MyTable
([Value])
VALUES
('16B'),
('23G'),
('128F'),
('128M')
;
You can do:
select top 1
case when SequenceChar = 'Z' then
cast((SequenceNum + 1) as varchar) + 'A'
else
cast(SequenceNum as varchar) + char(ascii(SequenceChar) + 1)
end as NextSequence
from (
select Value,
cast(substring(Value, 1, CharIndex - 1) as int) as SequenceNum,
substring(Value, CharIndex, len(Value)) as SequenceChar
from (
select Value, patindex('%[A-Z]%', Value) as CharIndex
from MyTable
) a
) b
order by SequenceNum desc, SequenceChar desc
SQL Fiddle Example
Assuming your column always follows the format you described (number+1 char suffix), you can do
WITH cte1 AS(
SELECT LEFT(your_column,LEN(your_column)-1) as num,
RIGHT(your_column,1) as suffix
FROM your_table),
cte2 AS (SELECT MAX(num) as max_num FROM cte1)
SELECT
CASE c.max_suffix
WHEN 'Z' THEN 'A'
ELSE NCHAR(UNICODE(c.max_suffix)+1)
END as next_suffix,
CASE c.max_suffix
WHEN 'Z' THEN a.max_num+1
ELSE a.max_num
END as next_num
FROM cte2 a
CROSS APPLY (SELECT MAX(suffix) as max_suffix FROM cte1 b WHERE b.num=a.max_num)c
;
I'm pretty sure there are other ways to do the same; also, my approach doesn't seem optimal, but I think it returns what you need...
No doubt it would be much better if you can redesign the table as Damien_The_Unbeliever recommends.
To generate alphanumeric String sequence in below format.
A B C.....Y Z AA AB......AZ BA BB.....BZ...go on.
CREATE OR REPLACE FUNCTION to_az(in_num number)
RETURN VARCHAR2
IS
num PLS_INTEGER := TRUNC (in_num) - 1;
return_txt VARCHAR2 (1) := CHR (65 + MOD (num, 26));
BEGIN
IF num <= 25
THEN
RETURN return_txt;
ELSE
RETURN to_az (FLOOR (num / 26))
|| return_txt;
END IF;
END to_az;
Ms-sql function to generate an alpha-numeric next sequence id like 'P0001','P0002' and so on.
ALTER FUNCTION NextProductID()
returns varchar(20)
BEGIN
DECLARE #NEXTNUMBER INT;
DECLARE #NEXTPRODUCTID VARCHAR(20);
SELECT #NEXTNUMBER=MAX( CONVERT(INT, SUBSTRING(PRODUCT_CODE,2,LEN(PRODUCT_CODE))))+1 FROM Product;
--PRINT #NEXTNUMBER;
SET #NEXTPRODUCTID=CONVERT(VARCHAR,#NEXTNUMBER)
SELECT #NEXTPRODUCTID='P'+REPLICATE('0',6-LEN(#NEXTPRODUCTID)) + #NEXTPRODUCTID;
return #NEXTPRODUCTID;
END
Here product is the table name and product_code is the column