2009-11-29 32 views
1

我试图做一个比one described here更简单的函数来获取购物车的订单号的下一个值。对于SQL Server的GetNextOrderNumber,需要非常简单的'序列'

  • 我不关心,如果有差距
  • 只完成订单获得一个ID(即我故意不使用IDENTITY)
  • 显然不能有重复
  • 我不关心性能和锁定。如果我们有这么多的新订单,我关心锁定,那么我会先遇到其他问题

我发现了很多其他类似的问题,但不是我正在寻找的确切解决方案。

我到目前为止是这样的:

USE [ShoppingCart] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Sequence_CompletedOrderID] 
([val] [int] NOT NULL 
    CONSTRAINT [DF_Sequence_CompletedOrderID_NextValue] DEFAULT ((520000)) 
) ON [PRIMARY] 

那么对于存储过程:

CREATE PROC dbo.GetNextCompletedOrderId 
    @nextval AS INT OUTPUT 
AS 

UPDATE dbo.sequence_completedorderid SET @nextval=val += 1; 
GO 

就像我说的,我想它的基础上我挂到上面的文章 - 所以也许这只是一个笨拙的做法。即使像这样简单的事情,以及我过去的睡前时间,我的SQL也不太适合。谢谢!

+0

@marc_s becasue我已经在使用身份。这是一个人类可读的序列号。订单表也包含不完整的订单 – 2009-11-29 10:10:03

+0

@Simon:好的 - 这是有道理的唯一原因:-) – 2009-11-29 10:12:35

+1

@marc_s接受了几个更多的答案:-)我总是在切线时脱身,当我开始做,但我'm试图做得更好 – 2009-11-29 10:27:45

回答

1

好了,你已经在你的主表的IDENTITY列 - 大约只具有再次有标识列附加表,但如何?这将节省你这么多的麻烦和麻烦.....

USE [ShoppingCart] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Sequence_CompletedOrderID] 
([val] [int] NOT NULL IDENTITY(520000, 1) 
) ON [PRIMARY] 



CREATE PROC dbo.GetNextCompletedOrderId 
    @nextval AS INT OUTPUT 
AS 
    INSERT INTO dbo.Sequence_CompletedOrderID DEFAULT VALUES 

    SELECT @nextval = SCOPE_IDENTITY() 
GO 

这样的话,你可以离开确保事情的所有的麻烦都是独一无二的等到SQL Server,它也将确保你赢了我们无法从IDENTITY列中取回相同的值!

+0

I 'd同意,但将其延长一点点,并附上一个订单号码栏 - 是它的概念上的冗余,但它为您提供了一点免费弹性。 – Murph 2009-11-29 10:32:34

+0

@murph和/或审计日期时间字段可能有助于诊断丢失通过在那里有一个日期时间值 - 再加上它有一个表只有一个单一的值 – 2009-11-29 10:41:20

+0

@marc_s是否有一个简单的方法来让价值刚刚更新每次都创建一个新行? nto,我太困扰任何方式。 – 2009-11-29 10:42:03

0

如何在将数据插入表格后使用以下语句?

UPDATE dbo.sequence_completedorderid 
SET @nextval = (SELECT MAX(val) + 1 FROM dbo.sequence_completedorderid) 
+0

这是怎么去处理并发?在高度压力的系统中你会得到很多重复的值 - 真的很糟糕的想法..... – 2009-11-29 10:19:51

+0

你没有保护,以防止几个客户端事务同时访问表“dbo.Sequence_CompletedOrderID),并获得相同的所有”下一个值“,如果你只有一个客户端,那么就工作得很好 - 当你有数百个客户端时,除了悲伤之外,什么都不会产生...... – 2009-11-29 10:29:39

+0

我知道SCOPE_IDENTITY(),但请求者没有使用标识列... – 2009-11-29 10:44:19

0

你不需要一个新的id列,所有你需要的是添加一个新的OrderCompleted列(位),并将它与你已有的id结合起来。

SELECT Id FROM T_Order WHERE OrderCompleted = 1 
+0

但我想要一个很好的顺序,所以当一个人正在看一堆打印出来的订单时,他们没有看到任何间隙 – 2009-11-29 10:32:57

+1

并且您的需求列表中的第一个语句是:**我不在乎是否存在间隙** – 2009-11-29 10:37:50

+0

好,所以我的意思是 - 如果由于我的应用程序层的意外情况,我得到的差距是好的,但我主要想要一个序列,在屏幕上看起来不错,从业务逻辑的角度来看这个陌生的 – 2009-11-29 10:48:02

1

从@marc_s的解决方案为产生的每一个号码的新行。起初我并不认为我喜欢这个,但意识到我可以利用它对我有利。

我所做的是添加了一个日期时间审计列,还有一个@orderid参数存储过程。对于特定的orderid,将保证返回相同的completedorderid,这是来自序列发生器的编号。

如果由于某种原因,我的应用程序层请求下一个id,但在可以提交事务之前崩溃 - 它仍然会链接到该顺序,以便当再次请求时,将返回相同的编号。

这是我结束了:

USE [ShoppingCart] 
GO 
/****** Object: Table [dbo].[Sequence_CompletedOrderID] Script Date: 11/29/2009 03:36:40 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Sequence_CompletedOrderID](
    [val] [int] IDENTITY(520000,1) NOT NULL, 
    [CreateDt] [datetime] NOT NULL CONSTRAINT [DF_Sequence_CompletedOrderID_CreateDt] DEFAULT (getdate()), 
    [Orderid] [int] NOT NULL CONSTRAINT [DF_Sequence_CompletedOrderID_Orderid] DEFAULT ((0)), 
CONSTRAINT [PK_Sequence_CompletedOrderID] PRIMARY KEY CLUSTERED 
(
    [Orderid] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 


USE [ShoppingCart] 
GO 
/****** Object: StoredProcedure [dbo].[GetCompletedOrderId] Script Date: 11/29/2009 03:34:08 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER PROC [dbo].[GetCompletedOrderId] 
    @orderid AS INT, 
    @completedorderid AS INT OUTPUT 
AS 

IF EXISTS (SELECT * FROM dbo.Sequence_CompletedOrderID WHERE orderid = @orderid) 
BEGIN 
    SET @completedorderid =(SELECT val FROM dbo.Sequence_CompletedOrderID WHERE orderid = @orderid) 
END 
ELSE 
BEGIN 
    INSERT INTO dbo.Sequence_CompletedOrderID (orderid) VALUES (@orderid) 
    SET @completedorderid =(SELECT SCOPE_IDENTITY()) 
END 
+0

似乎工作得很好,一旦你确定订单号应该是你生成它的问题,并保证它是静态的 - 即使有些事情发生了。它是在交易范围之外产生的,因此我需要小心。当用户进入确认页面时,我会生成订单号。这样我们就可以发邮件给他们,如果他们没有提交 - 并且已经有一个订单号给他们以供将来参考。如果他们没有得到那么多订单不会得到一个数字 – 2009-11-29 19:39:31

1

如果使用Sequence_CompletedOrderID表,订单ID的一排桌子,那么你应该使用UPDATE和依靠OUTPUT clause捕捉新的价值:

CREATE PROC dbo.GetNextCompletedOrderId 
    @nextval AS INT OUTPUT 
AS 
SET NOCOUNT ON; 
UPDATE dbo.Sequence_CompletedOrderID 
SET val=val + 1 
OUTPUT @nextval = INSERTED.val; 
GO 
相关问题