加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

sql server:按照计数器和另一个列值天生主键

发布时间:2021-03-09 20:47:49 所属栏目:编程 来源:网络整理
导读:我正在建设一个客户表,其父表是公司的. 已经声名(懊恼)我将为客户表建设一个主键,该主键是公司ID的组合,该公司ID是客户表中现有的varchar(4)列,譬喻,customer.company varchar(9)主键的别的部门应为零添补计数器,通过该公司内的客户数目递增. 譬喻. company =

我正在建设一个客户表,其父表是公司的.
已经声名(懊恼)我将为客户表建设一个主键,该主键是公司ID的组合,该公司ID是客户表中现有的varchar(4)列,譬喻,customer.company

varchar(9)主键的别的部门应为零添补计数器,通过该公司内的客户数目递增.

譬喻. company = MSFT,这是MSFT记录的第一个插入:PK应为MSFT00001
在后续插入时,PK将是MSFT00001,MSFT00002等.
然后当company = INTL并插入其第一笔记录时,第一笔记录将是INTL00001

我开始行使一个而不是触发器和一个我从其他stackoverflow相应建设的udf.

ALTER FUNCTION [dbo].[GetNextID]
(
  @in varchar(9)
)
RETURNS varchar(9) AS
BEGIN
    DECLARE @prefix varchar(9);
    DECLARE @res varchar(9);
    DECLARE @pad varchar(9);
    DECLARE @num int;
    DECLARE @start int;


if LEN(@in)<9


 begin
   set @in = Left(@in + replicate('0',9),9)
  end

SET @start = PATINDEX('%[0-9]%',@in);
SET @prefix = LEFT(@in,@start - 1 );


declare @tmp int;
 set @tmp = len(@in)
 declare @tmpvarchar varchar(9);
 set @tmpvarchar = RIGHT( @in,LEN(@in) - @start + 1 )
    SET @num = CAST(  RIGHT( @in,LEN(@in) - @start + 1 ) AS int  ) + 1
    SET @pad = REPLICATE( '0',9 - LEN(@prefix) - CEILING(LOG(@num)/LOG(10)) );
    SET @res = @prefix + @pad + CAST( @num AS varchar);

    RETURN @res
END

怎样编写my而不是触发器来插入值并增进此主键.可能我应该放弃它并开始一个割草营业?

歉仄,没有它,tmpvarchar变量SQL处事器给了我稀疏的功效.

办理要领

固然我赞成阻挡者的概念,但“接管不能改变的原则”倾向于低落整体压力程度,恕我直言.实行以下要领.

弱点

>仅限单排插入.您不会对新客户表举办任何批量插入,由于每次要插入行时都必要执行存储进程.
>密钥天生表存在必然水平的争用,因此存在阻塞的也许性.

可是,从好的方面来说,这种要领并没有任何与之相干的竞争前提,而且真正触犯我的感情并不是太严峻的黑客进攻.以是…

起首,从密钥天生表开始.它将包括每个公司的1行,包括您的公司标识符和每次执行插入时我们将要碰撞的整数计数器.

create table dbo.CustomerNumberGenerator
(
  company     varchar(8) not null,curr_value  int        not null default(1),constraint CustomerNumberGenerator_PK primary key clustered ( company ),)

其次,你必要一个像这样的存储进程(究竟上,你也许但愿将这个逻辑集成到认真插入客户记录的存储进程中.稍后具体先容).该存储进程接管公司标识符(譬喻“MSFT”)作为其独一参数.此存储进程执行以下操纵:

>将公司ID放入类型情势(譬喻,大写和修剪前导/尾随空格).
>假如该行尚不存在,则将该行插入密钥天生表(原子操纵).
>在单个原子操纵(更新语句)中,获取指定公司的计数器的当前值,然后递增.
>然后以指定的方法天生客户编号,并通过1行/ 1列SELECT语句返回给挪用方.

干得好:

create procedure dbo.GetNewCustomerNumber

  @company         varchar(8)

as

  set nocount                 on
  set ansi_nulls              on
  set concat_null_yields_null on
  set xact_abort              on

  declare
    @customer_number varchar(32)

  --
  -- put the supplied key in canonical form
  --
  set @company = ltrim(rtrim(upper(@company)))

  --
  -- if the name isn't already defined in the table,define it.
  --
  insert dbo.CustomerNumberGenerator ( company )
  select id = @company
  where not exists ( select *
                     from dbo.CustomerNumberGenerator
                     where company = @company
                   )

  --
  -- now,an interlocked update to get the current value and increment the table
  --
  update CustomerNumberGenerator
  set @customer_number = company + right( '00000000' + convert(varchar,curr_value),8 ),curr_value       = curr_value + 1
  where company = @company

  --
  -- return the new unique value to the caller
  --
  select customer_number = @customer_number
  return 0

go

您也许但愿将其集成到将行插入customer表的存储进程中的缘故起因是它将它们所有组合到一个事宜中;假如没有这个,当插入失败时,您的客户编号也许会/将会呈现间隙.

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读