Reputation: 9
My Table structure is
id type no amount
1 type1 a1 1000
2 type1 a2 2000
3 type2 b1 3000
4 type3 c1 4000
5 type1 a3 5000
6 type2 b2 6000
7 type2 b3 7000
8 type3 c2 8000
now i wants to increment the no
field data based on the type
.
for example for type1
the next no is a4
and
for numeric only I am using the following code
SELECT ISNULL(Max(No),0)+1 AS No FROM table
but how to do it for with Alphabets in SQL Server 2005
Upvotes: 0
Views: 2465
Reputation: 5120
Assuming that prefixes are of single character length, you may try following:
;with cte as (
select type, typePrefix = left(no, 1), typeNum = right(no, len(no) - 1)
from TableName
)
select typePrefix + cast(isnull(max(typeNum), 0) + 1 as varchar(10))
from cte
where type = 'type1'
group by typePrefix
But it will not work if you try to generate next no
for a type which is not in table (e.g. 'type4'). To allow it, you may need a separate table, where prefix for each type is specified:
create table TypePrefixes (type varchar(50), prefix varchar(10))
insert into TypePrefixes values ('type1', 'a')
insert into TypePrefixes values ('type2', 'b')
insert into TypePrefixes values ('type3', 'c')
insert into TypePrefixes values ('another_type', 'd')
--etc.
In this case, statement to get next no
will look as:
select tp.prefix + cast(isnull(max(cast(right(t.no, len(t.no) - len(tp.prefix)) as int)), 0) + 1 as varchar(20))
from TableName t
right join TypePrefixes tp on tp.type = t.type
where tp.type = 'type4'
group by tp.prefix
Also, you may just wish to calculate no
for each record on the fly, like:
;with cte as (
select *,
typeNum = row_number() over (partition by type order by id),
typePrefix = char(dense_rank() over (order by type) + ascii('a') - 1)
from TableName
)
select *, No2 = typePrefix + cast(typeNum as varchar(10))
from cte
However, the latter is limited in number of distinct types in your table, which should not exceed 26 (so that we not go beyond 'z').
Upvotes: 1
Reputation: 1
First, you need an UNIQUE index on No
column:
CREATE UNIQUE INDEX IUN_MyTable_On
ON MySchema.MyTable(On);
GO
This unique index will prevent duplicate values but, also, will help the query below.
Second, you could use this script to generate the next No
for a given letter:
DECLARE @Chr CHAR(1);
SET @Chr='A';
BEGIN TRY
BEGIN TRANSACTION;
DECLARE @LastId INT;
DECLARE @NewNo VARCHAR(...); -- Fill with No's max. length
-- Previous index will help this query
SELECT @LastId=MAX( CONVERT(INT,SUBSTRING(@LastNo,2,8000)) )
FROM MySchema.MyTable x WITH(UPDLOCK) -- It locks the rows to prevent a concurent session to generate the same value (No)
WHERE x.No LIKE @Chr+'%';
SET @NewNo=@Chr+CONVERT(VARCHAR(11),ISNULL(@LastId,0)+1);
-- Do whatever you want with the new value: ex. INSERT
INSERT INTO ... (No,...)
VALUES (@NewNo,...);
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
DECLARE @ErrMsg NVARCHAR(2000);
SET @ErrMsg=ERROR_MESSAGE();
IF @@TRANCOUNT>0
BEGIN
ROLLBACK;
END
RAISERROR(@ErrMsg,16,1);
END CATCH
Note #1: This solution should be safe if this is the only way to generate the new values (@NewNo
).
Note #2: If that SELECT query acquires at least 5000 locks then SQL Server will escalate locks at table/partition level.
Upvotes: 0
Reputation: 580
try something like
SELECT ISNULL(Max(No),0)+1 AS No FROM table group by type
Upvotes: 0