背景:我有一个名为Contact的数据库表。我系统中的所有用户在这个表中都有他们的联系人的详细信息,包括名字、姓氏和一个名为"UniqueId"的varchar字段。系统的用户可以在UniqueId字段中输入任何内容,只要它与该用户的其他联系人的唯一id唯一。
目的:我现在需要改变我的代码,使一个唯一的id自动生成,如果用户不提供一个。这应该是简短和视觉上令人愉快的。理想情况下,它可以是一个自动递增的数字。但是,AUTO_INCREMENT适用于整数字段,而不是varchar字段。
还要注意,每个联系人的UniqueId需要与该用户的其他联系人唯一,但不一定是整个系统唯一的。因此,以下uniqueid是有效的:
Contact
UserId Firstname Lastname UniqueId
1 Bob Jones 1
1 Harold Smith 2
2 Joe Bloggs 1
问题:那么,我该如何实现呢?是否有一个可靠的和干净的方式来获得数据库生成一个唯一的id为每个联系人在现有的UniqueId varchar字段(这是我的首选,如果可能的话)?或者我是否被迫让Java去获取下一个可用的唯一id,如果是这样,最可靠的方法是什么?或者有其他解决方案吗?
编辑- 11 April AM:我们使用hibernate来映射我们的字段。我刚开始研究这是否能提供另一种解决方案?任何意见吗?
编辑- 4月11日下午:目前有两个选择,但似乎都没有我想的那么理想。
1。正如@eis所建议的,除了当前的varchar字段之外,我还可以有一个自动递增的字段。然后,当保存联系人时,int也可以保存在varchar字段中,或者当检索联系人时,如果varchar为空,则可以使用int。但是使用两个字段而不是一个
会让人感觉混乱和错误。2。我正在考虑使用hibernate生成器,就像这里讨论的那样。但是这涉及到在其他地方保存下一个id和Java代码的计数,并且似乎大大使过程过于复杂。
如果我现有的唯一id字段是一个int字段,那么AUTO_INCREMENT就会工作,而且工作得很好。有没有办法使数据库生成这个,但将其保存为字符串?
我认为你真正应该做的是放弃当前的"唯一",并生成新的在整个系统中真正唯一的,总是自动生成的,而不是由用户提供的。您需要做一些单独的工作来迁移到新系统。这是我认为保持理智的唯一方法。如果需要的话,用户可以提供一些像别名这样的东西,这样看起来更赏心悦目。
好的方面是,您可以使用autoincrement。
好吧,如果你真的想要你想要的东西,还有一个额外的选择。你可以有一个像§§§§
这样的前缀,它永远不允许用户使用,并且总是基于它自动生成id,像§§§§1
, §§§§2
等。如果您不允许任何以该前缀开头的内容来自最终用户,您将知道不会有冲突,并且您可以在需要时逐一生成它们。
序列将是为它生成数字的理想选择。在MySQL中没有序列,但是你可以像这样模拟它们。
我很抱歉,我真的不知道MySQL语法,但这里是我如何在SQL Server中这样做。希望这对你们还是有价值的。基本上,我只是计算现有联系人的数量并将其作为varchar返回。
CREATE FUNCTION GetNewUniqueId
(@UserId int)
RETURNS varchar(3)
AS
BEGIN
DECLARE @Count int;
SELECT @Count = COUNT(*)
FROM Contacts
WHERE UserId = @UserId;
SET @Count = @Count + 1;
RETURN CAST(@Count AS varchar(3));
END
但是,如果您真的想要一些"视觉上令人愉悦"的东西,为什么不尝试返回更像Firstname + Lastname
的东西呢?
CREATE FUNCTION GetNewUniqueId
(@UserId int, @FirstName varchar(255), @LastName varchar(255))
RETURNS varchar(515)
AS
BEGIN
DECLARE @UniqueId varchar(515), @Count int;
SET @UniqueId = @FirstName + @LastName;
SELECT @Count = COUNT(*)
FROM Contacts
WHERE UserId = @UserId AND LEFT(UniqueId, LEN(@UniqueId)) = @UniqueId;
IF @Count > 0
SET @UniqueId = @UniqueId + '_' + CAST(@Count + 1 AS varchar(3));
RETURN @UniqueId;
END