【问题标题】:How to avoid duplicate values in SQL Server如何避免 SQL Server 中的重复值
【发布时间】:2017-03-03 03:55:18
【问题描述】:

我有近 10 台令牌机,客户从表 Token 中获取令牌号。我正在使用存储过程来访问该表并对其进行更新

Id    Name       TokenFrom   TokenTo   LastUsedToken
----------------------------------------------------
1     Token         551        999         562

我注意到,在高峰时段,很多客户收到重复号码。也许这个问题出现了,因为有 10 个客户同时/小时/秒获得令牌。

这里是issuedToken

Id  PosId   Barcode        Date                      Status  Number isTaken 
1   2       6282019214317  2016-10-20 09:41:45.020    1      366        1
2   2       6282019215918  2016-10-20 09:42:15.020    1         367     1
3   2       6282019225016  2016-10-20 09:42:45.020    1         368     1
4   3       6282019230812  2016-10-20 09:42:55.020    1         369     1

即使有时相同的号码也会出现在两台收银机上。我正在使用此 Update 语句获取和更新 POS 上的 Next Token Number

UPDATE POS 
SET tNo = (SELECT TOP 1 NUMBER 
           FROM Tickets 
           WHERE STATUS = 1 
             AND isTaken = 1 
             AND PosId = (SELECT CGROUP 
                          FROM POS 
                          WHERE NAME='ABC')) 
WHERE NAME = 'ABC'

我在一组中有 3-3 个 POS,这就是为什么选择 cGroup 而在表格中是 PosId

我之前在这个问题中问过与这个问题相关的问题,有人帮我编写了一个存储过程来轻松访问令牌号。

但我仍然遇到重复问题。谁能告诉我避免重复的最佳方法是什么?

What is Best Approach for Auto Increament

【问题讨论】:

  • @RyanVincent,客户正在令牌系统中输入 10 位国民身份证并获取令牌号码
  • 令牌只是一个递增的数字吗? (请解释)。使用sequenceidentity(插入一条记录,然后使用scope_identity)。任何其他复杂的 MAX 或手动锁定方法只会给您带来问题。
  • @RyanVincent,顺便说一句,我在出票时也会生成一个 13 位唯一条形码
  • @Nick.McDermaid,是的,它只是增加数字。没有别的
  • 我建议您使用身份或序列,但首先我必须说服为特殊目的使用特殊范围的票号是个坏主意。为什么女士需要1-50岁?如果你一天有超过 50 位女士会发生什么。无论如何,您是否链接到您的其他问题,因为那是您实现它的方式?那肯定会给你重复的令牌

标签: sql sql-server-2008 duplicates


【解决方案1】:

假设您拥有 SQL Server 2012(请澄清)

不是一个完整的答案,但如果你愿意,我可以扩展。

首先创建一个序列(只运行一次):

create sequence CustomerCare 
    as integer
    start with 51
    increment by 1
    minvalue 51
    maxvalue 350
    cycle;

现在从中获取下一个序列(随心所欲地运行它):

select next value for CustomerCare

此方法无法将相同的编号分配给两个不同的请求,因此您不会得到重复。当它达到 350 时,它将自动环绕。您可以为其他分组创建和使用序列。比其他解决方案简单得多,并且 100% 可靠。

我需要再次建议不要为特定组创建幻数范围。

【讨论】:

  • 我有 Sql Server 2008 R2
  • 所以即使20台令牌机同时请求号码也不会重复??
  • 我使用的是 Sql Server 2008 R2 Express Edition。当我尝试运行此查询时。这是错误。在 CREATE、DROP 或 ALTER 语句中使用的未知对象类型“序列”。
  • sequences 仅适用于 SQL Server 2012。我会更新您的帖子并考虑另一种解决方案
  • 是的,告诉我一些可以在 SQL Server 2008 R2 上运行的东西
【解决方案2】:

这是在 SQL 2008 中有效但不考虑分组、不重置并且具有不同的条形码公式的东西

这是令牌发行表。在此处插入记录“保留”令牌编号:

CREATE TABLE [dbo].[issuedToken2](
    [Token] [int] IDENTITY(1,1) NOT NULL,
    [Barcode]  AS (((6820000000.)+[Token])*(100)+[PosID]),
    [GenerationDate] [smalldatetime] NOT NULL,
    [PosID] [int] NOT NULL
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[issuedToken2] 
    ADD  CONSTRAINT [DF_issuedToken_GenerationDate]  
    DEFAULT (getdate()) FOR [GenerationDate]
GO

这是一个可用于获取令牌编号的存储过程。你可以有 100 个系统同时调用它,它们都会得到一个不同的号码:

CREATE PROC [dbo].[pGetToken]
@PosID INT
AS
BEGIN
SET NOCOUNT ON

insert into issuedToken2 (PosID) 
VALUES(@PosID)

RETURN scope_identity()
END
GO

这就是你如何使用它的方式:使用 posid(在本例中为 7)调用存储的 proc 以保留令牌编号,然后使用它来获取条形码:

DECLARE @Token INT

EXEC @Token = pGetToken 7

SELECT @Token, [Barcode]
FROM issuedToken2
WHERE Token=@Token

基本上这是通过使用identity - 一个递增的数字来实现的。我知道你现有的系统不能这样工作,但你没有解释为什么需要这样做。

【讨论】:

    【解决方案3】:

    我通过更改访问 Next Number 的存储过程得到了解决方案。现在的逻辑是锁定Token 表并获取下一个数字。现在我只得到唯一的数字。

    感谢大家的友好回复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-12
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 2019-09-24
      • 2016-07-04
      相关资源
      最近更新 更多