Ich bin auf diesen Beitrag gestoßen ( Was ist der Unterschied zwischen tinyint, smallint, mediumint, bigint und int in MySQL? ) Und habe festgestellt, dass PostgreSQL keine vorzeichenlose Ganzzahl unterstützt.
Kann jemand helfen zu erklären, warum es so ist?
Meistens verwende ich in MySQL eine vorzeichenlose Ganzzahl als automatisch inkrementierten Primärschlüssel. Wie kann ich dies in einem solchen Design überwinden, wenn ich meine Datenbank von MySQL nach PostgreSQL portiere?
Vielen Dank.
postgresql
unsigned-integer
Adrian Hoe
quelle
quelle
serial
(1 bis 2147483647) oderbigserial
(1 bis 9223372036854775807). Eine vorzeichenbehaftete 64-Bit-Ganzzahl bietet wahrscheinlich mehr als genug Platz.Antworten:
Es ist bereits beantwortet, warum in postgresql nicht signierte Typen fehlen. Ich würde jedoch vorschlagen, Domänen für nicht signierte Typen zu verwenden.
http://www.postgresql.org/docs/9.4/static/sql-createdomain.html
Domain ist wie ein Typ, jedoch mit einer zusätzlichen Einschränkung.
Für ein konkretes Beispiel könnten Sie verwenden
Hier ist, was psql gibt, wenn ich versuche, den Typ zu missbrauchen.
quelle
Es ist nicht im SQL-Standard enthalten, daher ist der allgemeine Drang, es zu implementieren, geringer.
Wenn zu viele verschiedene Ganzzahltypen vorhanden sind, ist das Typauflösungssystem anfälliger, sodass ein gewisser Widerstand gegen das Hinzufügen weiterer Typen zum Mix besteht.
Es gibt jedoch keinen Grund, warum dies nicht möglich ist. Es ist nur viel Arbeit.
quelle
to_char
Muster.Sie können eine CHECK-Einschränkung verwenden, z.
Auch PostgreSQL hat
smallserial
,serial
undbigserial
Typen für Auto-Inkrement.quelle
2^32-1
, während signierte Ints bis zu gehen können2^31-1
.NULL
undCHECK
sind vollständig orthogonal. Sie könnenNULL
/NOT NULL
Spalten mit oder ohne habenCHECK
. Beachten Sie nur , dass gemäß der Dokumentation bei postgresql.org/docs/9.4/ddl-constraints.html ,CHECK
NULL Werte TRUE zurückkehrt, wenn Sie also wirklich will NULLs verhindern, verwenden SieNOT NULL
stattdessen (oder zusätzlich zuCHECK
).integer
(nicht ohne dass sie zufällig positiv oder negativ sind).Das Gespräch über DOMAINS ist interessant, aber nicht relevant für den einzig möglichen Ursprung dieser Frage. Der Wunsch nach Ints ohne Vorzeichen besteht darin, den Bereich der Ints mit der gleichen Anzahl von Bits zu verdoppeln. Dies ist ein Effizienzargument und nicht der Wunsch, negative Zahlen auszuschließen. Jeder weiß, wie man eine Prüfbedingung hinzufügt.
Auf die Frage von jemandem sagte Tome Lane:
Was ist die "POLA"? Google hat mir 10 Ergebnisse gegeben, die bedeutungslos sind . Ich bin mir nicht sicher, ob es politisch falsch gedacht und daher zensiert ist. Warum sollte dieser Suchbegriff kein Ergebnis liefern? Was auch immer.
Sie können vorzeichenlose Ints als Erweiterungstypen ohne allzu große Probleme implementieren. Wenn Sie dies mit C-Funktionen tun, gibt es überhaupt keine Leistungseinbußen. Sie müssen den Parser nicht erweitern, um mit Literalen umzugehen, da PgSQL eine so einfache Möglichkeit bietet, Zeichenfolgen als Literale zu interpretieren. Schreiben Sie einfach '4294966272' :: uint4 als Ihre Literale. Casts sollten auch keine große Sache sein. Sie müssen nicht einmal Bereichsausnahmen ausführen, sondern können die Semantik von '4294966273' :: uint4 :: int einfach als -1024 behandeln. Oder Sie können einen Fehler auslösen.
Wenn ich das gewollt hätte, hätte ich es getan. Da ich Java auf der anderen Seite von SQL verwende, ist es für mich von geringem Wert, da Java auch keine vorzeichenlosen Ganzzahlen hat. Also gewinne ich nichts. Ich ärgere mich schon, wenn ich eine BigInteger aus einer Bigint-Spalte bekomme, wenn sie in lange passen sollte.
Eine andere Sache, wenn ich 32-Bit- oder 64-Bit-Typen speichern musste, kann ich PostgreSQL int4 bzw. int8 verwenden, wobei ich nur daran denke, dass die natürliche Reihenfolge oder Arithmetik nicht zuverlässig funktioniert. Das Speichern und Abrufen bleibt davon jedoch unberührt.
So kann ich ein einfaches vorzeichenloses int8 implementieren:
Zuerst werde ich verwenden
die minimalen 2 Funktionen
uint8_in
unduint8_out
ich muss zuerst definieren.müssen dies in C uint8_funcs.c implementieren. Also benutze ich das komplexe Beispiel von hier und mache es einfach:
na ja, oder du kannst es einfach schon erledigt finden .
quelle
Gemäß der neuesten Dokumentation wird die gesungene Ganzzahl unterstützt, jedoch keine vorzeichenlose Ganzzahl in der Tabelle. Der serielle Typ ähnelt jedoch dem vorzeichenlosen Typ, beginnt jedoch bei 1 und nicht bei Null. Aber die Obergrenze ist die gleiche wie gesungen. Das System hat also wirklich keine Unterstützung ohne Vorzeichen. Wie Peter betonte, steht die Tür offen, um die nicht signierte Version zu implementieren. Der Code muss möglicherweise viel aktualisiert werden, einfach zu viel Arbeit aus meiner Erfahrung mit der C-Programmierung.
https://www.postgresql.org/docs/10/datatype-numeric.html
quelle
Postgres hat einen vorzeichenlosen Integer-Typ, der vielen unbekannt ist :
OID
.Es ist jedoch kein numerischer Typ , und der Versuch, damit Arithmetik (oder sogar bitweise Operationen) durchzuführen, wird fehlschlagen. Außerdem sind es nur 4 Bytes (
INTEGER
), es gibt keinen entsprechenden 8-Byte-BIGINT
Typ ( ) ohne Vorzeichen.Es ist also keine gute Idee, dies selbst zu verwenden, und ich stimme allen anderen Antworten zu, dass Sie in einem Postgresql-Datenbankdesign immer eine
INTEGER
oderBIGINT
-Spalte für Ihren seriellen Primärschlüssel verwenden sollten - damit er negativ beginnt (MINVALUE
) oder zulässt um (CYCLE
) zu wickeln, wenn Sie die gesamte Domain erschöpfen möchten.Es ist jedoch sehr nützlich für die Eingabe / Ausgabe-Konvertierung, z. B. für die Migration von einem anderen DBMS. Das Einfügen des Werts
2147483648
in eine Ganzzahlspalte führt zu einem " FEHLER: Ganzzahl außerhalb des Bereichs ", während die Verwendung des Ausdrucks einwandfrei2147483648::OID
funktioniert.Wenn Sie eine Ganzzahlspalte als Text mit auswählen
mycolumn::TEXT
, erhalten Sie irgendwann negative Werte, aber mit erhaltenmycolumn::OID::TEXT
Sie immer eine natürliche Zahl.Sehen Sie ein Beispiel an dbfiddle.uk .
quelle