Domanda

Sto cercando di rendere una funzione ancora più semplice di uno descritto qui per ottenere il valore successivo di un numero d'ordine per un carrello.

  • Non mi importa se ci sono lacune
  • Solo gli ordini completati ottengono un ID (cioè non sto usando deliberatamente IDENTITÀ)
  • Ovviamente non devono esserci duplicati
  • Non mi interessano le prestazioni e il blocco. Se abbiamo così tanti nuovi ordini che mi preoccupo del lockin, allora avrò altri problemi

Ho trovato molte altre domande simili, ma non la soluzione esatta che sto cercando.

Quello che ho finora è questo:

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]

quindi per il proc memorizzato:

CREATE PROC dbo.GetNextCompletedOrderId 
  @nextval AS INT OUTPUT
AS

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

Come ho detto, sto cercando di basarlo sull'articolo a cui ho collegato sopra, quindi forse questo è solo un modo goffo di farlo. Il mio SQL non è abbastanza all'altezza anche per cose semplici come questa, ed è passata la mia ora di andare a letto. Grazie!

È stato utile?

Soluzione

OK, quindi hai già una colonna IDENTITY nella tua tabella principale - ma che ne dici di avere una tabella aggiuntiva con di nuovo una colonna IDENTITY ?? Questo ti risparmierebbe così tanti problemi e seccature .....

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

In questo modo, puoi lasciare tutta la seccatura di assicurarti che le cose siano uniche ecc. su SQL Server, e assicurerai anche che non otterrai mai lo stesso valore due volte dalla colonna IDENTITY!

Altri suggerimenti

Se si utilizza la tabella Sequence_CompletedOrderID come tabella a una riga di ID ordine, è necessario utilizzare UPDATE e fare affidamento su clausola OUTPUT per acquisire il nuovo valore:

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

La soluzione di @marc_s crea una nuova riga per ogni numero generato. All'inizio non pensavo che mi piacesse, ma mi sono reso conto che posso usarlo a mio vantaggio.

Ciò che ho fatto è stata aggiunta una colonna di controllo della data e ora e anche un parametro @orderid al proc memorizzato. Per un particolare orderid sarà garantito la restituzione dello stesso completeorderid , che è il numero del generatore di sequenza.

Se per qualche motivo il mio livello applicazione richiede l'id successivo, ma poi si arresta in modo anomalo prima di poter eseguire il commit della transazione, sarà comunque collegato a quell'ordine in modo che quando viene richiesto nuovamente verrà restituito lo stesso numero.

Questo è quello che ho finito con:

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

Che ne dici di usare la seguente dichiarazione dopo aver inserito i dati nella tua tabella?

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

Non hai bisogno di una nuova colonna id, tutto ciò che serve è aggiungere una nuova colonna (bit) OrderCompleted e combinarla con l'id che hai già.

SELECT Id FROM T_Order WHERE OrderCompleted = 1
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top