我想创建一个使用存储过程创建序列号的过程。
我有三张桌子:
表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个数字。我正面临着如何在使用相同项目类型或不同项目类型的下一个不同项目批次编号时使用日期增加第五位数字检查的值的问题。如果您有任何疑问,请告诉我。提前致谢。
答案 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
我看到一些不恰当的事情 - 没有必要意味着有错误。 对不起,我不了解真正的商业规则 - 他们可能会以不同的方式解释事情。 我假设最简单,最有用的逻辑。
所以表格看起来像这样:
ItemType(PK) ItemTypeDescr
a Type A
b Most Usable Type B
c Free text for type C
要避免77需要在ItemBatchNumber + ItemType上添加一些唯一索引或设置PK。 但在任何情况下,设置为22,55和11,44 ..是正常预期的。所以你的SP将失败。
此处查询可能会返回多行(22,55):
set @IitemType=(Select ItemType from ItemBatchNumber where ItemBatchNumber=@ItemBatchNumber)
或者:
Select @IitemType = ItemType from ItemBatchNumber where ItemBatchNumber=@ItemBatchNumber
如果是多行,它将返回最后一行。
但无论如何它是不正确的 - 如果@ItemBatchNumber =' WB2'预计会有哪些价值' b'或者' c'?
...
... 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),而不是一个独特的
一个。在您添加新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