【问题标题】:Auto Generated Serial Number using Stored Procedure使用存储过程自动生成序列号
【发布时间】:2015-02-26 19:52:03
【问题描述】:

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

我有三张桌子:

表 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位应该是这样的:

在一天中,对于一个项目类型的第一个项目批号 - 第 5 位应该是 1,并且在当天保持 1。对于下一个项目批号,它应该是 2,并且在当天保持 2。

对于第二天应用相同的规则。

例如,假设“b”项目类型有 3 个项目批号 WB1、WB2、WB3。如果今天有人首先选择“b”项目类型的 WB2(项目批号),那么序列号应该是 xyzb1,对于今天的 WB2,它将保持 xyzb1。现在,如果接下来有人选择 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 位是从我的代码中正确生成的。当使用相同项目类型或不同项目类型的下一个不同项目批号时,我面临如何增加第五位数字检查的值的问题。如果您有任何疑问,请告诉我。提前致谢。

【问题讨论】:

  • 请尝试格式化您的问题以便于阅读。
  • 其实我不知道该怎么做:(
  • 使用问题编辑器中的{} 按钮相应地获取代码和其他格式化工具。
  • 如果“xyz”是一个常数,我建议它不应该是序列号的一部分。这里只有噪音。对于您的第 5 个字符,为什么不使用另一个 ROW_NUMBER 日期作为排序标准?

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


【解决方案1】:

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

我认为这里的挑战是您需要您的存储过程增加一个变量跨批次并每天“重新开始”。这将向我建议您需要该程序 1. 跟踪上次运行的时间,看看是不是今天。 2. 跟踪今天运行了多少次。

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

【讨论】:

  • 对不起。它应该是项目批号而不是电线批号
  • 对您有帮助的一件事是存储过程打算做什么:它是打算用它获得的值更新表,还是将值提供给外部程序或报告等。如果要更新表,问题要简单得多。
  • 不需要更新表,我只需要创建序列号。
  • 创建序列号后,它会发生什么?它是否存储在数据库中的某个位置?
  • 我的意思是说,这个存储过程在调用的时候结果会怎样?
【解决方案2】:

让我们填充一些数据:

物品类型:

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   !!
...

项目制造:

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) 作为唯一代码。

所以表格应该是这样的:

ItemType(PK)    ItemTypeDescr
a               Type A
b               Most Usable Type B
c               Free text for type C
  1. ItemBatchNumber - 匹配表 - 定义批次和 ItemTypes 之间的匹配。 它可能有标有“!”的数据,这是有效的。

为避免 77 需要添加一些唯一索引或在 ItemBatchNumber+ItemType 上设置 PK。 但无论如何设置为 22,55 和 11,44.. 是正常预期的。所以你的 SP 会失败。

  1. 在这里你会得到一个错误。

此处查询可能返回多行 (22, 55):

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

或者:

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

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

但无论如何它是不正确的 - 如果 @ItemBatchNumber = 'WB2' 预期哪个值是 'b' 或 'c'?

  1. 错误:

...

... 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:

一个。在(之前)您添加新 ItemMfg 时,需要检查当前日期。

b.对于任何现有的 ItemMfg 行(对于 555),您需要从 count() 中排除 555 之后的所有 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

b.对于任何已经存在的 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

【讨论】:

  • 对不起。它应该是项目批号而不是电线批号
  • 感谢您的回复。对于特定的项目类型和项目批号,SN 在一天内应该是唯一的。如果我不使用项目批号作为输入参数,那么 SN 的第 5 位将如何增加。没有使用制造日期或 ItemMfg 表。我只需要根据一天选择的Item批号和项目类型生成一个序列号。
  • 如果不使用任何日期,如何知道一天中选择了哪种项目类型?如果有人选择了 WB2 - 你怎么知道它是今天而不是昨天被选中的?
  • > 假设“b”项目类型有 3 个项目批号 WB1、WB2、WB3,因此 ItemBatchNumber 有 3 行。没有信息是否选择了 WB2,WB1 是先选择还是第二选择。一天都没有。
  • 应该是其他表(ItemMfg?) - 日志,它告诉 - 在第 1 天选择的 WB2 - 在第 1 天选择的 WB1 - 在第 2 天选择的 WB2 - 在第 2 天选择的 WB2 - 在第 2 天选择的 WB3
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多