Jag tror inte att det finns ett enkelt sätt som är lika enkelt som vanliga sekvenser, eftersom:
- En sekvens lagrar endast en nummerström (nästa värde, etc.). Du vill ha en för varje partition.
- Sekvenser har speciell hantering som kringgår den aktuella transaktionen (för att undvika tävlingstillståndet). Det är svårt att replikera detta på SQL- eller PL/pgSQL-nivå utan att använda knep som dblink.
- DEFAULT kolumnegenskapen kan använda ett enkelt uttryck eller ett funktionsanrop som
nextval('myseq')
; men den kan inte referera till andra kolumner för att informera funktionen från vilken ström värdet ska komma.
Du kan göra något som fungerar, men du kommer förmodligen inte att tycka att det är enkelt. Åtgärda ovanstående problem i sin tur:
- Använd en tabell för att lagra nästa värde för alla partitioner, med ett schema som
multiseq (partition_id, next_val)
. -
Skriv en
multinextval(seq_table, partition_id)
funktion som gör något i stil med följande:- Skapa en ny transaktion oberoende av den aktuella transaktionen (ett sätt att göra detta är genom dblink; jag tror att vissa andra serverspråk kan göra det lättare).
- Lås tabellen som nämns i
seq_table
. - Uppdatera raden där partitions-id är
partition_id
, med ett ökat värde. (Eller infoga en ny rad med värde 2 om det inte finns någon befintlig.) - Beslut den transaktionen och returnera det tidigare lagrade ID:t (eller 1).
-
Skapa en infogningstrigger i din projekttabell som använder ett anrop till
multinextval('projects_table', NEW.Project_ID)
för infogningar.
Jag har inte använt hela denna plan själv, men jag har provat något liknande för varje steg individuellt. Exempel på multinextval
funktion och utlösaren kan tillhandahållas om du vill försöka detta...