Ho bisogno della chiave Auto-incrementale come, ma come?

1

Ho un modello aziendale specifico per la memorizzazione dei loro ID. È nel formato di yy-mm-autoincrement .

Potrei semplicemente memorizzare date e incremental id, ma c'è un altro problema. Dovrebbe essere riavviato ogni anno.

Ok, quindi ora avere PK di auto-incremento è ora inutile vero? Poiché in realtà non è auto-incrementale.

Potrei fare qualcosa come where id LIKE yy-mm- per ottenere l'ultimo massimo per l'anno in corso, ottenere l'ultima cifra e aggiungere 1 giusto?

No.

Perché?

  • L'ultimo valore è 18-08-90 e poi è stato eliminato
  • 18-08-89 è l'ultimo più alto
  • aggiungi 1 ed è ora 18-08-90

Sì, può essere univoco dal momento che 18-08-90 è già stato cancellato, quindi non c'è più la duplicazione giusta? Per il lato commerciale, no.

Ciò di cui ho bisogno in base all'ultimo esempio è 18-08-91

Possibile soluzione a cui potrei pensare:

  • crea un'altra tabella chiamata x_identities
  • ha una colonna chiamata date e incremental (o counter )

In che modo questo risolve il problema? Supponiamo che abbia 18-08-xx e 90 come riga. Userò il PK come PK + FK sulla tabella x .

Quindi ora quando ho eliminato 18-08-90 , l'ultimo valore incrementale è presente sulla tabella x_identities e ora può fare + 1

Ora, l'unico problema è, come posso ottenere il prossimo valore disponibile dal lato dell'app?

Potrei avere getNextId() che inserisce una nuova riga lì giusto? anno e 'ultimo incremento + 1? Quindi usa quello? (Sì inserire invece di leggere solo perché concorrenza?)

Ho paura di no Se l'app esegue continuamente quella query, genererà ID non utilizzati. E se controllo per primo se non viene utilizzato, potrei ricevere un ID da un record che è stato cancellato.

Non sono bravo in SQL. C'è qualche funzione SQL che può aiutarmi con questo? Trigger? Procedure?

Potrei aggiungere anche perché questo potrebbe aiutare, la ragione per cui ho bisogno di un ID prima è perché il progetto sta seguendo DDD. Impossibile creare entità con stato non valido in modo che sia richiesto new Entity(Id, ....) . Che cosa mi raccomanderebbe i medici di DDD qui?

    
posta doesnotmatter 19.08.2018 - 07:56
fonte

1 risposta

2

Ho affrontato un requisito simile a very qualche tempo fa. Tuttavia, ci sono state un paio di cose che influenzano la mia decisione che potrebbero non essere applicabili alla situazione descritta nella risposta:

  1. Dovevo farlo usando MariaDB / MySQL
  2. Gli utenti dovevano vedere l'ID mentre inserivano i dati per il record.
  3. La parte incrementale non ha bisogno di essere consecutivi (ad esempio alcuni potrebbero essere saltati).

Ho usato una tabella con una singola riga (id 1) e TAVOLI DI LOCK funzione:

CREATE TABLE id_increment_generator(
    id INT NOT NULL,
    increment INT NOT NULL AUTO_INCREMENT,
    year INT(4) NOT NULL,
    month INT(2) NOT NULL
)

Quando qualcuno ha aperto il modulo per inserire un nuovo record, ho eseguito questo codice per produrre il nuovo ID:

Run(LOCK TABLES id_increment_generator)
try {
    generatorRow = RUN(SELECT * FROM id_increment_generator WHERE id = 1)
    if (generatorRow not present) {
        RUN(INSERT INTO id_increment_generator VALUES (id, increment, year, month) VALUES (1, 1, YEAR(NOW()), MONTH(NOW())))
        return 1
    }

    if (generatorRow.year != CURRENT_YEAR || generatorRow.month != CURRENT_MONTH) {
        RUN(UPDATE id_increment_generator SET increment = 2 WHERE id = 1)
        return 1
    }

    increment = generatorRow.increment
    RUN(UPDATE id_increment_generator SET increment = increment + 1 WHERE id = 1)
    return increment
}
finally {
    Run(UNLOCK TABLES)
}

Ha funzionato abbastanza bene. Non so quanto bene questo scale, ma data la semantica, nulla è davvero in grado di scalare bene. La semantica richiede di sincronizzarsi sull'intero sistema.

Detto questo, PostgreSQL ha sequenze. Sono praticamente ciò che fa il mio codice sopra, ma non si ripristinano regolarmente. Se si utilizza Postgres, è possibile creare sequenze anziché eseguire manualmente il comando SELECT / UPDATE.

    
risposta data 20.08.2018 - 07:51
fonte

Leggi altre domande sui tag