Domanda

In Oracle esiste un meccanismo per generare numeri di sequenza, ad es.;

CREATE SEQUENCE supplier_seq

    MINVALUE 1
    MAXVALUE 999999999999999999999999999
    START WITH 1
    INCREMENT BY 1
    CACHE 20;

E poi esegui la dichiarazione

supplier_seq.nextval

per recuperare il numero di sequenza successivo.

Come creeresti la stessa funzionalità in MS SQL Server?

Modificare:Non sto cercando modi per generare automaticamente le chiavi per i record della tabella.Devo generare un valore univoco che posso utilizzare come ID (logico) per un processo.Quindi ho bisogno dell'esatta funzionalità fornita da Oracle.

È stato utile?

Soluzione

Non esiste una corrispondenza esatta.

L'equivalente è IDENTITY che puoi impostare come tipo di dati durante la creazione di una tabella.SQLSERVER creerà automaticamente un numero di sequenza in esecuzione durante l'inserimento.L'ultimo valore inserito può essere ottenuto chiamando SCOPE_IDENTITY() o consultando la variabile di sistema @@IDENTITY (come sottolineato da Frans)

Se hai bisogno dell'equivalente esatto, dovresti creare una tabella e quindi scrivere una procedura per restituire il valore successivo e altre operazioni.Vedi la risposta di Mark sulle insidie ​​​​in merito.

Modificare:
SQL Server ha implementato la sequenza simile a Oracle.Si prega di fare riferimento a questa domanda per maggiori dettagli.

Come implementeresti le sequenze in Microsoft SQL Server?

Altri suggerimenti

L'identità è la soluzione migliore e più scalabile, MA, se hai bisogno di una sequenza che non è un int incrementante, come 00A, 00B, 00C o qualche sequenza speciale, c'è un secondo metodo migliore. Se implementato correttamente, si ridimensiona OK, ma se implementato male, si ridimensiona male. Esito a raccomandarlo, ma quello che fai è:

  1. Devi memorizzare il " valore successivo " in un tavolo. La tabella può essere una tabella semplice, una riga e una colonna con solo quel valore. Se hai diverse sequenze, possono condividere la tabella, ma potresti avere meno contese avendo tabelle separate per ognuna.
  2. Devi scrivere una singola istruzione di aggiornamento che aumenterà quel valore di 1 intervallo. Puoi inserire l'aggiornamento in un proc memorizzato per renderlo semplice da usare e impedire di ripeterlo nel codice in luoghi diversi.
  3. Usare correttamente la sequenza, in modo che si ridimensioni in modo ragionevole (no, non così come Identitiy :-) richiede due cose: a. l'istruzione update ha una sintassi speciale creata per questo esatto problema che incrementerà e restituirà il valore in una singola istruzione; b. devi recuperare il valore dalla sequenza personalizzata PRIMA dell'inizio di una transazione e al di fuori dell'ambito della transazione. Questo è uno dei motivi per cui l'identità si ridimensiona: restituisce un nuovo valore indipendentemente dall'ambito della transazione, per qualsiasi tentativo inserito, ma non ripristina in caso di errore. Ciò significa che non si bloccherà, e anche che avrai delle lacune per le transazioni fallite.

La sintassi dell'aggiornamento speciale varia leggermente in base alla versione, ma il punto è che si esegue un'assegnazione a una variabile e l'aggiornamento nella stessa istruzione. Per il 2008, Itzik Ben-Gan ha questa soluzione chiara: http: / /www.sqlmag.com/Articles/ArticleID/101339/101339.html?Ad=1

Il metodo old-school 2000 e successivi si presenta così:

UPDATE SequenceTable SET @localVar = valore = valore + 5 - cambia la coda alla tua logica di incremento

Questo incrementerà e restituirà il valore successivo.

Se non puoi assolutamente avere lacune (resisti a quel requisito :-), è tecnicamente possibile mettere quell'aggiornamento o procedere a fianco del resto della tua transazione, ma subisci un GRANDE colpo di concorrenza mentre ogni inserto attende quello precedente impegnarsi.

Non posso prendermi il merito su questo; Ho imparato tutto da Itzik.

trasforma il campo in campo Identità. Il campo otterrà automaticamente il suo valore. Puoi ottenere l'ultimo valore inserito chiamando SCOPE_IDENTITY () o consultando la variabile di sistema @@ IDENTITY

La funzione SCOPE_IDENTITY () è preferita.

Come ha detto DHeer, non esiste assolutamente una corrispondenza esatta. Se provi a creare la tua procedura per farlo, invariabilmente impedirai al ridimensionamento della tua applicazione.

Le sequenze di Oracle sono altamente scalabili.

OK, lo riprendo leggermente. Se sei davvero disposto a concentrarti sulla concorrenza e sei disposto a prendere i numeri fuori servizio come è possibile con una sequenza, hai una possibilità. Ma dal momento che sembri piuttosto sconosciuto con t-sql per cominciare, inizierei a cercare alcune altre opzioni quando (il porting di un'app Oracle su MSSS - è quello che stai facendo)

Ad esempio, basta generare un GUID tra " nextval " funzione. Sarebbe in scala.

Oh e NON utilizzare una tabella per tutti i valori, solo per mantenere il valore massimo nella cache. Dovresti bloccarlo per assicurarti di dare valori univoci ed è qui che smetterai di ridimensionare. Dovrai capire se esiste un modo per memorizzare nella cache i valori in memoria e l'accesso programmatico a una sorta di blocchi leggeri: blocchi di memoria, non blocchi di tabelle.

Vorrei che SQL Server avesse questa funzionalità. Semplificherebbe tante cose.

Ecco come sono riuscito a risolverlo.

Crea una tabella chiamata tblIdentities. In questa tabella inserisci una riga con i valori minimo e massimo e la frequenza con cui reimpostare il numero di sequenza. Inserisci anche il nome di una nuova tabella (chiamalo tblMySeqNum). In questo modo l'aggiunta di più generatori di numeri di sequenza in seguito è abbastanza semplice.

tblMySeqNum ha due colonne. ID (che è un'identità int) e InsertDate (che è una colonna di data e ora con un valore predefinito di GetDate ()).

Quando è necessario un nuovo numero seq, chiamare uno sproc che si inserisce in questa tabella e utilizzare SCOPE_IDENTITY () per ottenere l'identità creata. Assicurati di non aver superato il massimo in tblIdentities. Se hai quindi restituito un errore. In caso contrario, restituisci il tuo numero di sequenza.

Ora, per ripristinare e pulire. Avere un lavoro che viene eseguito regolarmente, se necessario, che controlla tutte le tabelle elencate in tblIdentites (solo una per ora) per vedere se è necessario ripristinarle. Se hanno raggiunto il valore o l'ora di ripristino, chiamare DBCC IDENT RESEED sul nome della tabella elencata nella riga (tblMySeqNum in questo esempio). Questo è anche un buon momento per cancellare le nostre righe extra di cui non hai davvero bisogno in quella tabella.

NON eseguire la pulizia o il reseeding nel tuo sproc che ottiene l'identità. In tal caso, il generatore di numeri di sequenza non verrà ridimensionato affatto.

Come ho detto, renderebbe così tante cose più facili di questa funzionalità in SQL Server, ma ho scoperto che questo lavoro attorno funziona abbastanza bene.

Vaccano

Se riesci ad aggiornare a SQL Server 2012 puoi usare gli oggetti SEQUENCE. Anche SQL Server 2012 Express ha il supporto per le sequenze.

CREATE SEQUENCE supplier_seq
    AS DECIMAL(38)
    MINVALUE 1
    MAXVALUE 999999999999999999999999999
    START WITH 1
    INCREMENT BY 1
    CACHE 20;

SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq
SELECT NEXT VALUE FOR supplier_seq

Risultati in:

---------------------------------------
1

(1 row(s) affected)


---------------------------------------
2

(1 row(s) affected)


---------------------------------------
3

(1 row(s) affected)


---------------------------------------
4

(1 row(s) affected)


---------------------------------------
5

(1 row(s) affected)

Basta fare attenzione a specificare il giusto tipo di dati. Se non lo avessi specificato il MAXVALUE che hai fornito non sarebbe accettato, ecco perché ho usato DECIMAL con la massima precisione possibile.

Ulteriori informazioni su SEQUENCES qui: http://msdn.microsoft.com/en -us / library / ff878091.aspx

Questo potrebbe essere già stato risposto molto tempo fa ... ma da SQL 2005 in poi è possibile utilizzare la funzione ROW_NUMBER ... un esempio potrebbe essere:

select ROW_NUMBER() OVER (ORDER BY productID) as DynamicRowNumber, xxxxxx,xxxxx

L'istruzione OVER utilizza ORDER BY come chiave primaria univoca nel mio caso ...

Spero che questo aiuti ... niente più tabelle temporanee o strani join !!

Non proprio una risposta, ma sembra che le sequenze arriveranno su SQL Server nel 2012.

http: //www.sql-server-performance .com / 2011 / sequenza-sql-server-2011 /

Non una risposta esatta ma aggiunta ad alcune risposte esistenti

SCOPE_IDENTITY (Transact-SQL)

  

SCOPE_IDENTITY, IDENT_CURRENT e @@ IDENTITY sono funzioni simili   perché restituiscono valori che vengono inseriti nelle colonne identità.

     

IDENT_CURRENT non è limitato da ambito e sessione; è limitato a   tabella specificata. IDENT_CURRENT restituisce il valore generato per a   tabella specifica in qualsiasi sessione e qualsiasi ambito. Per ulteriori informazioni, vedere   IDENT_CURRENT (Transact-SQL).

Significa che due sessioni diverse possono avere lo stesso valore di identità o numero di sequenza, quindi per evitarlo e ottenere un numero univoco per tutte le sessioni utilizzare IDENT_CURRENT

Esattamente per questo IDENT_CURRENT non è limitato da ambito e sessione; è limitato a una tabella specificata. dobbiamo usare SCOPE_IDENTITY () perché l'identità dell'ambito ci fornirà un numero univoco generato nella nostra sessione e l'unicità è fornita dall'identità stessa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top