【问题标题】:Auto Increment varchar datatype set as primary keyAuto Increment varchar 数据类型设置为主键
【发布时间】:2014-04-29 20:45:30
【问题描述】:

我创建了一个表,其中Id 列为varchar(20)

我需要一个可以将id 加 1 的存储过程。

我试过这个:

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

但是在第 10 条记录之后它就不起作用了。

【问题讨论】:

  • not working after 10th record ... 需要进一步澄清。
  • 因此您希望 varchar 表现得像一个数字,但您对它不符合规定感到失望。好吧,用一个数字
  • BAD...Users_Id varchar(20), Cat_Id varchar(20),
  • 我的第二个猜测:query_id 被声明为 varcharchar 没有长度。默认值为 1。

标签: asp.net sql stored-procedures database-design type-conversion


【解决方案1】:

Query_id 的选择从您的表格更改为下方

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

基于戈登的评论;我的理解是,由于 ID 是 varchar max(id) 没有获取正确的最大值,但它会这样做。

例如试试这个

create table testtab (id varchar(10));

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

如果你在下面说它会返回 53

select MAX(id) from testtab

但是这个会返回 200

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

SQL SERVER 2008 R2测试

【讨论】:

  • 请解释一下这会有什么不同?
  • @GordonLinoff,我认为这是有道理的,但是拥有varchar 类型的代理键并以这种方式自动递增它是非常丑陋的设计。
  • @HamletHakobyan,同意;不建议这样做,ID 列应该是已经在 cmets 中指出的 INT 列。因此,如果有帮助,请考虑解决问题。
【解决方案2】:

你知道你的存储过程有一个隐含的竞争条件,不是吗?

在您计算新的查询 id 和您的表插入提交之间,另一个会话可以进来,得到完全相同的查询 id,插入它并提交。猜猜当您的插入尝试提交时会发生什么?胜率第一;第二个得到一个重复的键错误。不要问我是怎么知道的:)

如果您确实需要文本查询 id,您可以尝试使用计算字段,如下所示:

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 ,
)

那么你的存储过程如下所示:

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

【讨论】:

    【解决方案3】:

    听起来您的应用程序需要一个字符串作为 ID 字段,但在数据库中您希望它的 ID 表现为自动递增的整数字段。

    考虑在数据库中使用整数,当您检索该值并需要将其用作字符串时,此时将值转换为字符串,无论是在您的查询中还是在您的应用程序中。

    这会解决你的问题。

    【讨论】:

      【解决方案4】:

      您必须认真审查您的设计。我会建议这样的。

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-29
        • 2013-09-09
        • 1970-01-01
        • 2017-04-05
        • 1970-01-01
        • 2019-12-30
        • 2014-12-27
        • 2017-05-03
        相关资源
        最近更新 更多