Вопрос

I have created a table with an Id column as varchar(20).

I need a stored procedure which can increment id by 1.

I have tried this:

ALTER PROCEDURE dbo.spInsertCatQuery
    (@Users_Id varchar(20),
     @Cat_Id varchar(20),
     @Query varchar(100),
     @Query_Title varchar(50)
)
AS
BEGIN
    Declare @Query_Id bigint

    SELECT @Query_Id = coalesce((select max(Query_Id) + 1 from tblCatQuery), 1);

    INSERT INTO tblCatQuery 
    VALUES(@Query_Id, @Users_Id, @Cat_Id, @Query_Title, @Query) 
END

But it is not working after 10th record.

Это было полезно?

Решение

Change the selection of Query_id from your table to below

SELECT @Query_Id= 
coalesce((select max(cast(Query_Id as int)) + 1 from tblCatQuery), 1);

Based on Gordon's comment; my understanding is that since ID is varchar max(id) is not fetching the correct max value but casting it will do so.

For example try this

create table testtab (id varchar(10));

insert into testtab values(2),(200),(53)

If you say below it will return 53

select MAX(id) from testtab

but this one will return 200

select MAX(cast(id as int)) from testtab

Tested in SQL SERVER 2008 R2

Другие советы

You do know your stored procedure has an implicit race condition, don't you?

Between your calculating the new query id and your table insert getting committed, another session can come in, get exactly the same query id, insert it and get committed. Guess what happens when your insert tries to commit? First in wins; the second gets a duplicate key error. Don't ask me how I know this :)

If you really need a text query id, you might try using a computed field, something like this:

create table dbo.tblCatQuery
(
  query_id      int not null identity(1,1) primary key clustered ,
  query_id_text as right('0000000000'+convert(varchar,id),10) ,
  user_id       varchar(20)  not null ,
  cat_id        varchar(20)  not null ,
  query         varchar(100) not null ,
  query_title   varchar(50)  not null ,
)

Then your stored procedure looks like this:

create procedure dbo.spInsertCatQuery

  @Users_Id    varchar(20)  ,
  @Cat_Id      varchar(20)  ,
  @Query       varchar(100) ,
  @Query_Title varchar(50)  ,
  @Query_ID    varchar(10)  output

AS

  insert dbo.tblCatQuery ( user_id   , cat_id  , query_title  , query  )
  VALUES                 ( @Users_Id , @Cat_Id , @Query_Title , @Query )

  -- give the caller back the id of the row just inserted
  set @Query_ID = @@SCOPE_IDENTITY

  -- for redundancy, hand it back as the SP's return code, too
  return @Query_ID

GO

It sounds like your application needs a string for the ID field, yet in the database you want it ID to behave as an auto-incrementing integer field.

Consider using an integer in the database, and when you retrieve the value and need to use it as as string, at that point convert the value to a string, either in your query or in your application.

This will solve your problem.

You must seriously review your design. I shall suggest something like this.

CREATE TABLE tblCatQuery(QueryId int NOT NULL PRIMARY KEY IDENTITY(1, 1), 
        UserId int NOT NULL REFERENCES tblUsers(UserId),
        CatId int NOT NULL REFERENCES tblCat(CatId),
        Query varchar(100), Query_Title varchar(50))

CREATE TABLE tblUsers(UserId int NOT NULL PRIMARY KEY IDENTITY(1, 1), ....
CREATE TABLE tblCat(CatId int NOT NULL PRIMARY KEY IDENTITY(1, 1), ....

CREATEPROCEDURE dbo.spInsertCatQuery
(
        @Users_Id int,
        @Cat_Id int,
        @Query varchar(100),
        @Query_Title varchar(50)
)
AS
BEGIN
    INSERT INTO tblCatQuery(Users_Id, Cat_Id, Query_Title, Query)
    VALUES( Users_Id, Cat_Id, Query_Title, Query) 
END
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top