我已经获得了非常具体的业务要求,而且我无法将其翻译为在我们的数据库中工作。
我们有多个部门,他们都处理我们称之为文件的事务。每个文件都有唯一的标识符,但是如何分配此标识符取决于与文件关联的部门。
部门ABC,DEF和GHI需要系统为他们提供遵循模式的下一个标识符......而部门JKL和MNO需要能够指定他们自己的标识符。
生成的文件编号是半复杂的,这进一步加剧了这一点。他们的文件编号遵循以下模式:
[a-z]{3,4}\d{2}-\d{4}
(一个3或4个字母前缀,对应于具有两个数字对应年份的部门,一个破折号后跟一个四位数生成的数字 - 即ABC13-0001)
破折号之前的部分很容易生成...文件表具有对具有前缀列的部门表的强制外键引用,我可以轻松地获取年份。这是冲刺之后的部分,我似乎无法解决。
这是一个四位数的标识符。每个部门都需要下一个生成的ID尽可能顺序到他们的部门(我说尽可能顺序,因为我知道即使身份规范也会留下空白)。最重要的是,我们需要每年将其重置为0001。所有这一切,同时确保没有重复,这是所有这一切中最重要的部分。
因此,我们只有一个由所有这些部门使用的文件表。因此,为了能够处理JKL和MNO,我将FileNumber字段设置为具有唯一约束的varchar(12)。他们可以输入他们需要的任何东西,只要它是独一无二的。这让我只知道如何为其他部门生成唯一的文件编号。
我的第一直觉是给文件表一个代理身份主键,以确保即使生成的文件号出错,每个记录也能保证唯一的标识符。
然后我会创建一个单行表,每个部门有两列,一个用于数字,一个用于日期。该数字将是给定部门(作为int)的4位数字标识符后缀的最后使用数字,日期将是指定时间。存储日期将让我检查自上次id被拉动后年份是否已更改,以便我可以分配1,而不是lastid + 1.
然后,文件表上的插入触发器将使用:
生成文件ID触发器最终将使用上次使用的id和日期更新实用程序表。
理论上,我认为这样可行......并且对文件id列的唯一约束将阻止生成的文件ID已存在的插入。但它感觉如此脆弱,我可以预见,如果触发器无法更新实用程序表,那么唯一约束就是一把双刃剑,可能会阻止部门创建新文件。毕竟,如果没有,那么下次生成文件号时,它会尝试使用相同的生成ID,并失败。必须有更好的方法。
我的另一个想法是每个部门都有一个表,只有一个标识整数列和非空日期字段,默认值为(getdate())...并让文件表上的触发器插入一个新行,并使用该ID。它还负责删除给定部门ID表中的所有行,并在新的一年重置身份。对我来说感觉更安全,但是我有5个实用程序表(每个部门自动生成id 1个),最多有9999条记录,只是为了生成一个id。
我错过了一些简单的东西吗?我是以正确的方式来做这件事的吗?我不禁想到必须有一个更简单的方法。我是否正确尝试让SQL服务器对此负责,或者我应该在我将在此数据库之上构建的桌面应用程序中尝试这样做吗?
答案 0 :(得分:1)
所以,我认为你可能过于复杂了。我也可能误解了这些要求。我不相信你需要单独的表或任何东西,你只需要检查现有的ID并增加它们。 SQLFiddle现在似乎没有工作,但这是我在本地数据库中提出的方法:
create table dept_ids (
id varchar(12) primary key
)
insert into dept_ids values('ABC13-0001')
insert into dept_ids values('DEF13-0001')
insert into dept_ids values('GHI13-0001')
insert into dept_ids values('JKL13-0001')
insert into dept_ids values('ABC13-0002')
declare
@dept varchar(4)
, @year varchar(2)
, @prefix varchar(8)
, @new_seq int
set @dept = 'ABC'
select @year = right(cast(DATEPART(yy, getdate()) as varchar(4)), 2)
set @prefix = @dept + @year + '-'
select @new_seq = isnull(right(max(id), 4), 0) + 1 from dept_ids where id like @prefix + '%'
select new_id = @prefix + right(replicate('0', 4) + cast(@new_seq as varchar(4)), 4)
通过使用getdate()和ISNULL检查,当然可以处理不同的部门以及年份场景。对于可以输入自己的序列值的部门,您只需为该参数添加空检查,并跳过生成此值(如果存在)。
如果我过于简单化,请随时告诉我,我会调整。