• You're having problems with this mainly because you are working with one row at a time. Your control table is updated once for each row inserted, instead of updating it once with the whole range of numbers required. We've been here before - you're very new to SQL so let's try and work this through. I think that converting this stored procedure to a set-based equivalent would be best achieved in two steps, with the first being a cleanup and re-arrangement of the code, like this:

    ALTER Procedure [dbo].[BS_Voucher_CreateVoucher]

    @vouchertypeID int = 1,

    @denomination int = 100,

    @quantity int = 10,

    @amountvalue int = 100,

    @userid varchar(50) = 1,

    @validateDays int = 40

    AS

    --BEGIN

    SET NOCOUNT ON;

    DECLARE

    @vouchertype varchar(20),

    @transactionID varchar(20),

    @count int =1,

    @max-2 int,

    @vouchertypenew varchar(20),

    @retval varchar(20),

    @voucherstatus int

    SELECT @vouchertype = VoucherType FROM GV_VoucherType WHERE VoucherTypeID = @vouchertypeID

    IF @vouchertype IS NULL

    RETURN -1

    SELECT @voucherstatus = VoucherStatusId FROM GV_VoucherStatus WHERE VoucherStatus = 'New'

    SELECT @transactionID = ISNULL(vouchervalue,0) FROM gv_vouchervalue WHERE voucherabbreviation = 'TRNID'

    SELECT @max-2 = ISNULL(vouchervalue,0) FROM gv_vouchervalue WHERE voucherabbreviation = 'V'+@retval

    SET @vouchertypenew = RTRIM(LTRIM(@vouchertype));

    SET @retval = LEFT(@vouchertypenew,1);

    WHILE CHARINDEX(' ',@vouchertypenew,1)>0

    BEGIN

    SET @vouchertypenew = LTRIM(RIGHT(@vouchertype,LEN(@vouchertype) - CHARINDEX(' ',@vouchertype,1)));

    SET @retval += LEFT(@vouchertypenew,1);

    END

    WHILE @count <= @quantity

    BEGIN

    --If EXISTS (SELECT VoucherType FROM GV_VoucherType WHERE VoucherType = @vouchertype)

    --BEGIN

    INSERT INTO GV_Voucher

    VALUES

    (

    @vouchertypeID,

    'V'+@retval + Replace( Str( @max-2 + @count, 7), ' ', '0') ,

    @denomination,

    DATEADD(MM,6,GETDATE()),

    GETDATE(),

    GETDATE(),

    @voucherstatus,

    'TRN' + Replace( Str( @transactionID + 1, 7), ' ', '0'),

    @quantity,

    CASE @vouchertypenew

    WHEN 'Discount' THEN @amountvalue

    ELSE 0

    END,

    @userid,

    @userid,

    @validateDays,

    0

    )

    SET @count = @count + 1

    --END

    END

    UPDATE gv_vouchervalue

    SET vouchervalue = @max-2 + @count

    WHERE voucherabbreviation = 'V'+@retval

    UPDATE gv_vouchervalue

    SET VoucherValue = @transactionID + 1

    WHERE VoucherAbbreviation = 'TRNID'

    --END

    RETURN 0

    Test it. If there are errors, list them in detail. When it's working, it's quite straightforward to perform step 2.

    “Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden