使用存储过程自动生成序列号

时间:2015-02-26 19:52:04

标签: sql sql-server-2008 stored-procedures generator serial-number

我想创建一个使用存储过程创建序列号的过程。

我有三张桌子:

表1:

create table ItemTypes
(
    ItemTypeID int not null primary key,
    ItemType varchar(30)
)

表2:

create table ItemBatchNumber
(
     ItemBatchNumberID int not null primary key,
     ItemBatchNumber varchar(20),
     ItemType varchar(30),
)

表3:

 create table ItemMfg
    (
        ManufactureID int not null primary key,
        ItemBatchNumberID int foreign key references     ItemBatchNumber(ItemBatchNumberID),
SerialNumber varchar(10),
        MfgDate datetime 
    )

对于每个项目类型,有几个项目批次编号。

现在,序列号的前3位是xyz。序列号的4位数应为项类型(例如,如果项类型为'b',则序列号应为xyzb)。

序列号的5位数应该是这样的:

在一天中,对于第一个项目,第一个项目的批次编号 - 第五个数字应为1,并且当天将保持为1。对于下一个项目批次编号,它应为2,并且当天将保持为2。

第二天适用同样的规则。

例如假设'b'项目类型有3个项目批号WB1,WB2,WB3。如果今天有人首先选择'b'项目类型的WB2(项目批号),那么序列号应该是xyzb1,它今天将保留xyzb1用于WB2。现在,如果有人选择了WR1,那么今天的序列号应为xyzb2。明天将首先选择“b”项目类型的项目批次编号,对于该批次编号,该类型序列号应为xyzb1。同样的规则适用于其他项目类型。

我一直试过:

   create procedure Gen_SerialNumber
    (
    @ManufactureID int,
    @IitemType varchar(30),
    @ItemBatchNumberID int,
    @Date datetime,
     @SerialNumber out,
    @fifthDigit int out
    )
    AS
    Begin 
    set @IitemType=(Select ItemType from ItemBatchNumber where ItemBatchNumber=@ItemBatchNumber)
    Declare @SerialNumber1 varchar(20)
    Set @SerialNumber1= 'xyz'+''+@IitemType+''+CAST( (Select COUNT(distinct ItemBatchNumber)from ItemBatchNumber
    where   ItemType=@IitemType) as varchar (10) )
    Set @fifthDigit=SUBSTRING(@SerialNumber1,5,1)
   IF EXISTS(SELECT SerialNumber FORM ItemMfg WHERE SerialNumber=null or         SerialNumber!=@SerialNumber)
                          SET @fifthDigit=1
        IF EXISTS(SELECT mfgDate,ItemBatchNumberID FROM ItemMfg WHERE mfgDate=@Date and ItemBatchNumberID=@ItemBatchNumberID)
                          SET @fifthDigit=1
                     ELSE 
                          SET @fifthDigit=@fifthDigit+1
    SET @SerialNumber=('xyz'+''+@ItemType+''+cast(@fifthdigit as varchar(2)))
INSERT INTO ItemMfg VALUES(@ItemType,@ItemBatchNumberID,@SerialNumber,@Date)
END

我是SQL新手。从我的代码中正确生成SN的4个数字。我正面临着如何在使用相同项目类型或不同项目类型的下一个不同项目批次编号时使用日期增加第五位数字检查的值的问题。如果您有任何疑问,请告诉我。提前致谢。

2 个答案:

答案 0 :(得分:0)

您的问题有两个问题:我对您的存储过程中WireBatchNumber列的外观感到困惑,因为它未包含在您提供的表定义中。其次,最后一个@ItemType(在结束命令之前)拼写错误。

我认为这里的挑战是你需要你的存储过程增加一个变量跨批次和#34;重新开始"每天。那会告诉我你需要这个程序 1.跟踪上次运行的时间,看看它是否是今天。 2.跟踪今天运行的次数。

这不是一个非常初学者级别的知识类型的任务,但有一种方法,显然:how to declare global variable in SQL Server..?。使用此链接中提到的变量类型,您可以设置一些条件结构,使用DateDiff()函数将日期变量与今天进行比较,更改日期变量并重置计数器(如果两个日期在不同的日期),则递增项目批次编号的计数器,并使用此计数器提供第五位数字。

答案 1 :(得分:0)

让我们填充一些数据:

ItemTypes:

ItemTypeID  ItemType
1           a
2           b
3           c

ItemBatchNumber:

ItemBatchNumberID   ItemBatchNumber ItemType
...
11                  WB1             b
22                  WB2             b   !
33                  WB3             b   !!
44                  WB1             c
55                  WB2             c   !
66                  WB3             c   !!
77                  WB3             c   !!
...

ItemMfg:

ManufactureID   ItemBatchNumberID   MfgDate
111             22                  2015-03-01 7:00 -> xyzb1
222             11                  2015-03-01 8:00 -> xyzb1
333             22                  2015-03-01 9:00 -> xyzb2

444             33                  2015-03-02 5:00 -> xyzb1
555             33                  2015-03-02 6:00 -> xyzb2
666             11                  2015-03-02 7:00 -> xyzb1
777             33                  2015-03-02 8:00 -> xyzb3
888             11                  2015-03-02 9:00 -> xyzb2
999             22                  2015-03-02 9:35 -> xyzb1

我看到一些不恰当的事情 - 没有必要意味着有错误。 对不起,我不了解真正的商业规则 - 他们可能会以不同的方式解释事情。 我假设最简单,最有用的逻辑。

  1. ItemTypes - 看起来像查找表。但是你不使用ItemTypeID,而是使用它的值(a,b,c)作为唯一代码。
  2. 所以表格看起来像这样:

    ItemType(PK)    ItemTypeDescr
    a               Type A
    b               Most Usable Type B
    c               Free text for type C
    
    1. ItemBatchNumber - 匹配表 - 定义批次和ItemTypes之间的匹配。 它可能包含标有"!"的数据,这是有效的。
    2. 要避免77需要在ItemBatchNumber + ItemType上添加一些唯一索引或设置PK。 但在任何情况下,设置为22,55和11,44 ..是正常预期的。所以你的SP将失败。

      1. 这里你会收到一个错误。
      2. 此处查询可能会返回多行(22,55):

        set @IitemType=(Select ItemType from ItemBatchNumber where ItemBatchNumber=@ItemBatchNumber)
        

        或者:

        Select @IitemType = ItemType from ItemBatchNumber where ItemBatchNumber=@ItemBatchNumber
        

        如果是多行,它将返回最后一行。

        但无论如何它是不正确的 - 如果@ItemBatchNumber =' WB2'预计会有哪些价值' b'或者' c'?

        1. 错误:
        2. ...

          ... and ItemTypeID=@IitemType ...
          

          ItemTypeID是int; @IitemType是char(' b') - 您期望什么?

          ...

          MfgDate=@Date
          

          日期' 2015-03-02 5:00'和' 2015-03-02 7:00'不一样,但是在同一天。

          ...

          ...from ItemBatchNumber,ItemMfg
          where MfgDate=@Date 
              and ItemBatchNumber=@ItemBatchNumber 
              and ItemTypeID=@IitemType
          

          即使ItemBatchNumber将返回一行,而date也不会计算时间,它将从一天开始从ItemMfg返回所有批次。 你需要做正确的加入。

          ...

          Select COUNT(distinct ItemBatchNumber)
          

          你总是需要(count()+ 1),而不是一个独特的

          1. 我不确定,何时需要生成SN:
          2. 一个。在您添加新ItemMfg之前(之前),然后需要检查当天。

            湾对于任何已存在的ItemMfg行(对于555),则需要在555之后从count()中排除所有rqws。


            查询的外观如何:

            <强>一个。 (在添加新的ItemMfg-row时 - 传递用于创建ItemMfg-row的值)

            create procedure AddNewItemMfg    -- ...and generate SN
            (
               @ItemBatchNumberID int,
               @MfgDate datetime        -- pass getdate()
            ) AS Begin 
            
            -- calc 5th digit:
            declare @fifthDigit int;
            select 
                @fifthDigit = count(*) + 1
            from ItemBatchNumber AS bb
            inner join ItemMfg ii ON ii.ItemBatchNumberID = bb.ItemBatchNumberID 
            where bb.ItemBatchNumberID = @ItemBatchNumberID             -- single ItemBatchNumber-row to get ItemType
                and ii.MfgDate <= @MfgDate                              -- all previous datetimes
                and cast(ii.MfgDate as date) = cast(@MfgDate as date)   -- same day
            
            -- ManufactureID is Identity (i.e. autoincremented)
            INSERT INTO ItemMfg (ItemBatchNumberID, MfgDate, SerialNumber)
                SELECT @ItemBatchNumberID
                    , @MfgDate
                    , 'xyz' + bb.ItemType + cast(@fifthDigit as varchar(5))
                FROM ItemBatchNumber bb
                WHERE bb.ItemBatchNumber = @ItemBatchNumber
            ;
            
            end
            

            <强>湾对于任何已存在的ItemMfg-row

            create procedure GenerateSNforExistedItemMfg
            (
               @ManufactureID int
            ) AS Begin 
            
            -- generate SN - same as previous but in single query
            declare @SN varchar(10);
            Select @SN = 'xyz'
                + bb.ItemType
                + cast(
                    select count(*) + 1
                    from ItemMfg mm                         -- single row from mm
                    inner join ItemBatchNumber AS bb        -- single row from bb
                        ON bb.ItemBatchNumberID = mm.ItemBatchNumberID
                    inner join ItemMfg ii                   -- many matched rows
                        ON ii.ItemBatchNumberID = bb.ItemBatchNumberID 
                    where mm.ManufactureID = @ManufactureID -- single row from mm
                        and ii.MfgDate <= mm.MfgDate        -- all previous datetimes
                        and cast(ii.MfgDate as date) = cast(mm.MfgDate as date) -- same day
            
                as varchar(5))
            FROM ItemBatchNumber AS bb
            INNER JOIN ItemMfg ii ON ii.ItemBatchNumberID = bb.ItemBatchNumberID 
            WHERE ii.ManufactureID = @ManufactureID 
            
            -- update SN
            UPDATE ItemMfg SET
                SerialNumber = @SN
            WHERE ii.ManufactureID = @ManufactureID;
            
            end