Hier ist eine Möglichkeit, eine Spalte zu erstellen, die bei 1000000 beginnt und automatisch einen eindeutigen Wert zuweist, der ungefähr dem vorherigen Wert +1 entspricht (grob weil eine ID wegen fehlgeschlagener Transaktionen und möglicherweise anderer Fälle "übersprungen" werden könnte)).
Diese Antwort ist spezifisch für PostgreSQL, da sie die PostgreSQL-spezifischen Funktionen setval
und pg_get_serial_sequence
verwendet.
Migration:
defmodule MyApp.Repo.Migrations.CreateCompany do
use Ecto.Migration
def up do
create table(:companies, primary_key: false) do
add :number, :serial, primary_key: true
timestamps()
end
execute "select setval(pg_get_serial_sequence('companies', 'number'), 999999)"
end
def down do
drop table(:companies)
end
end
Modell:
defmodule MyApp.Company do
use MyApp.Web, :model
@primary_key false
schema "companies" do
field :number, :integer, primary_key: true, read_after_writes: true
timestamps()
end
end
Demo:
iex(1)> Repo.insert! %Company{}
[debug] QUERY OK db=2.7ms queue=0.1ms
INSERT INTO "companies" ("inserted_at","updated_at") VALUES ($1,$2) RETURNING "number" [{{2016, 12, 5}, {15, 57, 44, 0}}, {{2016, 12, 5}, {15, 57, 44, 0}}]
%MyApp.Company{__meta__: #Ecto.Schema.Metadata<:loaded, "companies">,
inserted_at: #Ecto.DateTime<2016-12-05 15:57:44>, number: 1000000,
updated_at: #Ecto.DateTime<2016-12-05 15:57:44>}
iex(2)> Repo.insert! %Company{}
[debug] QUERY OK db=4.5ms
INSERT INTO "companies" ("inserted_at","updated_at") VALUES ($1,$2) RETURNING "number" [{{2016, 12, 5}, {15, 57, 44, 0}}, {{2016, 12, 5}, {15, 57, 44, 0}}]
%MyApp.Company{__meta__: #Ecto.Schema.Metadata<:loaded, "companies">,
inserted_at: #Ecto.DateTime<2016-12-05 15:57:44>, number: 1000001,
updated_at: #Ecto.DateTime<2016-12-05 15:57:44>}
iex(3)> Repo.insert! %Company{}
[debug] QUERY OK db=3.4ms queue=0.1ms
INSERT INTO "companies" ("inserted_at","updated_at") VALUES ($1,$2) RETURNING "number" [{{2016, 12, 5}, {15, 57, 45, 0}}, {{2016, 12, 5}, {15, 57, 45, 0}}]
%MyApp.Company{__meta__: #Ecto.Schema.Metadata<:loaded, "companies">,
inserted_at: #Ecto.DateTime<2016-12-05 15:57:45>, number: 1000002,
updated_at: #Ecto.DateTime<2016-12-05 15:57:45>}
Einige Anmerkungen:
gesetzt ich 999999
den Sequenzwert die nächste Zahl in der Folge 1000000
- ist
I read_after_writes: true
auf die Säule gegeben, um sicherzustellen, da der Wert für dieses Feld von der Datenbank erzeugt wird, und ohne read_after_writes
Satz zu true
, das Feld wird nach dem Einfügen nicht erneut geladen und bleibt nil
.
Gibt es einen Grund, warum Sie keine automatische Inkrement-Taste dafür verwenden? – Dogbert
Ja, weil ich die Nummer als ID verwenden möchte. Ist es nicht eine gute Übung? –
Was meinst du mit "generiere eine Nummer" dann? Ein ganzzahliger Schlüssel mit automatischem Inkrement würde Datensätze mit den Werten 0, 1, 2, ... erzeugen. – Dogbert