2009-11-29 3 views
1

Я пытаюсь сделать еще более простую функцию, чем one described here, чтобы получить следующее значение номера заказа для корзины покупок.Нужно очень простая «последовательность» для GetNextOrderNumber для SQL Server

  • Я не волнует, если есть пробелы
  • только завершенные заказы получить идентификатор (т.е. я намеренно не использую 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 Я уже использую идентификатор. это читаемый пользователем порядковый номер. в таблице заказов также содержатся неполные заказы –

+0

@Simon: ОК - это единственная причина, когда это имеет смысл :-) –

+1

@marc_s принял еще несколько ответов :-) Я всегда сошел с тангенса, когда я начал делать это, но я Я пытаюсь быть лучше –

ответ

1

ОК, так что у вас уже есть столбец IDENTITY в главной таблице, - но как насчет просто иметь дополнительную таблицу с снова есть столбец 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 Согласны ли вы с этим, но добавьте его в маленький бит и добавьте столбец номера заказа тоже - да, его условно избыточно, но он дает вам немного отказов бесплатно. – Murph

+0

@murph и/или поле datetime для аудита могут помочь в диагностике отсутствующих значения, так как там есть время datetime - плюс это оправдывает наличие таблицы с одним значением в нем. –

+0

@marc_s - это простой способ иметь значение, просто обновленное, чем создавать новую строку каждый раз? что я слишком обеспокоен в любом случае. –

0

Как насчет использования следующей инструкции после вставки данных в таблицу?

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

Как tis goign обрабатывает параллелизм ?? Вы получите много дублированных значений в сильно напряженной системе - действительно очень плохая идея ..... –

+0

у вас нет защиты от нескольких клиентских транзакций, одновременно получающих доступ к таблице «dbo.Sequence_CompletedOrderID», и все они получают одинаковые " следующее значение "из этой таблицы. Прекрасно работает, если у вас только один клиент, - ничего не происходит, кроме горя, когда у вас есть сотни ... –

+0

Я знаю о SCOPE_IDENTITY(), но запросчик не использовал столбцы идентификаторов ... –

0

Вам не нужен новый столбец идентификаторов, все, что вам нужно, это добавить новый столбец OrderCompleted (бит) и объединить его с уже имеющимся идентификатором.

SELECT Id FROM T_Order WHERE OrderCompleted = 1 
+0

, но я хочу красивую последовательность, поэтому, когда человек смотрит на заказы, напечатанные в куче, они не видят пробелов –

+1

adn еще первое утверждение в вашем списке требований: ** Мне все равно, есть ли пробелы ** –

+0

ok, поэтому я действительно имел в виду - если из-за неожиданных обстоятельств в моем прикладном уровне я получаю пробел, который хорош, но я в первую очередь хочу, чтобы последовательность, которая будет хорошо смотреться на экране для непрофессионала –

1

Решение от @marc_s создает новую строку для каждого генерируемого числа. Сначала я не думал, что мне это нравится, но я понял, что могу использовать его в своих интересах.

Что я сделал, было добавлено столбец проверки даты, а также параметр @orderid для хранимой процедуры. Для конкретного orderid будет гарантировано вернуть тот же номер completedorderid, который является номером из генератора последовательности.

Если по какой-то причине мой прикладной уровень запрашивает следующий идентификатор, а затем сработает, прежде чем он сможет зафиксировать транзакцию, он все равно будет привязан к этому порядку, чтобы при повторном запросе возвращался тот же номер.

Это то, что я закончил с:

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

с точки зрения бизнес-логики похоже, тоже хорошо работает, как только вы решили, что номер заказа должен быть проблемой, которую вы его генерируете, и гарантированно, что он статичен, даже если что-то фанки продолжается. он генерируется вне сферы действия транзакции, и поэтому мне нужно быть осторожным. Я генерирую номер заказа, когда пользователь попадает на страницу подтверждения. таким образом, мы можем отправить их по электронной почте, если они не совершают, - и уже получили номер заказа, чтобы дать им информацию в будущем. если они не получают то далеко заказ не получает номер –

1

Если вы используете Sequence_CompletedOrderID таблицу с одной строкой таблицы идентификаторов заказов, то вы должны использовать 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