Je suis tombé sur ce post ( Quelle est la différence entre tinyint, smallint, mediumint, bigint et int dans MySQL? ) Et réalisé que PostgreSQL ne prend pas en charge les entiers non signés.
Quelqu'un peut-il aider à expliquer pourquoi il en est ainsi?
La plupart du temps, j'utilise un entier non signé comme clé primaire auto-incrémentée dans MySQL. Dans une telle conception, comment puis-je surmonter cela lorsque je porte ma base de données de MySQL vers PostgreSQL?
Merci.
postgresql
unsigned-integer
Adrian Hoe
la source
la source
serial
(1 à 2147483647) oubigserial
(1 à 9223372036854775807). Un entier 64 bits signé offre probablement plus de place qu'assez.Réponses:
On a déjà répondu pourquoi postgresql manque de types non signés. Cependant, je suggérerais d'utiliser des domaines pour les types non signés.
http://www.postgresql.org/docs/9.4/static/sql-createdomain.html
Le domaine est comme un type mais avec une contrainte supplémentaire.
Pour un exemple concret, vous pourriez utiliser
Voici ce que donne psql lorsque j'essaye d'abuser du type.
la source
Ce n'est pas dans la norme SQL, donc l'envie générale de l'implémenter est plus faible.
Le fait d'avoir trop de types d'entiers différents rend le système de résolution de type plus fragile, il y a donc une certaine résistance à l'ajout de types supplémentaires dans le mélange.
Cela dit, il n'y a aucune raison pour que cela ne puisse pas être fait. C'est juste beaucoup de travail.
la source
to_char
modèle.Vous pouvez utiliser une contrainte CHECK, par exemple:
De plus, PostgreSQL a
smallserial
,serial
et desbigserial
types pour l'incrémentation automatique.la source
2^32-1
, tandis que les entiers signés peuvent aller jusqu'à2^31-1
.NULL
etCHECK
sont complètement orthogonales. Vous pouvez avoirNULL
/NOT NULL
colonnes avec ou sansCHECK
. Notez simplement que, selon la documentation sur postgresql.org/docs/9.4/ddl-constraints.html ,CHECK
renvoyer NULL donne la valeur TRUE, donc si vous voulez vraiment empêcher les NULL, utilisez à laNOT NULL
place (ou en plus deCHECK
).integer
(non sans qu'elles soient aléatoirement positives ou négatives, au moins ..)Le discours sur DOMAINES est intéressant mais pas pertinent pour la seule origine possible de cette question. Le désir des entiers non signés est de doubler la plage des entiers avec le même nombre de bits, c'est un argument d'efficacité, pas le désir d'exclure les nombres négatifs, tout le monde sait comment ajouter une contrainte de vérification.
Lorsque demandé par quelqu'un à ce sujet , Tome Lane a déclaré:
Qu'est-ce que le "POLA"? Google m'a donné 10 résultats qui n'ont aucun sens . Je ne sais pas si c'est une pensée politiquement incorrecte et donc censurée. Pourquoi ce terme de recherche ne donnerait-il aucun résultat? Peu importe.
Vous pouvez implémenter des entiers non signés en tant que types d'extension sans trop de problèmes. Si vous le faites avec des fonctions C, il n'y aura pratiquement aucune pénalité de performance. Vous n'aurez pas besoin d'étendre l'analyseur pour traiter les littéraux car PgSQL a un moyen si simple d'interpréter les chaînes comme des littéraux, écrivez simplement '4294966272' :: uint4 comme vos littéraux. Les moulages ne devraient pas non plus être un problème. Vous n'avez même pas besoin de faire des exceptions de plage, vous pouvez simplement traiter la sémantique de '4294966273' :: uint4 :: int comme -1024. Ou vous pouvez lancer une erreur.
Si je le voulais, je l'aurais fait. Mais comme j'utilise Java de l'autre côté de SQL, pour moi, cela n'a guère de valeur puisque Java n'a pas non plus ces entiers non signés. Alors je ne gagne rien. Je suis déjà ennuyé si j'obtiens un BigInteger d'une colonne bigint, alors qu'il devrait tenir dans long.
Une autre chose, si j'avais besoin de stocker des types 32 bits ou 64 bits, je peux utiliser PostgreSQL int4 ou int8 respectivement, en me souvenant simplement que l'ordre naturel ou l'arithmétique ne fonctionnera pas de manière fiable. Mais le stockage et la récupération ne sont pas affectés par cela.
Voici comment je peux implémenter un simple int8 non signé:
Je vais d'abord utiliser
les 2 fonctions minimales
uint8_in
etuint8_out
je dois d'abord définir.besoin de l'implémenter dans C uint8_funcs.c. Je vais donc utiliser l'exemple complexe d'ici et le rendre simple:
ah bien, ou vous pouvez juste le trouver déjà fait .
la source
Selon la dernière documentation, l'entier singé est pris en charge mais pas d'entier non signé dans la table. Cependant, le type de série est un peu similaire à unsigned sauf qu'il commence à 1 et non à zéro. Mais la limite supérieure est la même que celle chantée. Le système n'a donc vraiment pas de support non signé. Comme l'a souligné Peter, la porte est ouverte pour mettre en œuvre la version non signée. Le code devra peut-être être mis à jour beaucoup, trop de travail de mon expérience de travail avec la programmation C.
https://www.postgresql.org/docs/10/datatype-numeric.html
la source
Postgres a un type entier non signé qui est à beaucoup unbeknownst:
OID
.Ce n'est pas un type numérique cependant, et essayer de faire de l'arithmétique (ou même des opérations au niveau du bit) avec lui échouera. De plus, il ne s'agit que de 4 octets (
INTEGER
), il n'y a pas deBIGINT
type non signé correspondant à 8 octets ( ).Ce n'est donc pas vraiment une bonne idée de l'utiliser vous-même, et je suis d'accord avec toutes les autres réponses que dans une conception de base de données Postgresql, vous devez toujours utiliser une colonne
INTEGER
ouBIGINT
pour votre clé primaire série - en la faisant commencer par la négative (MINVALUE
) ou en l'autorisant pour boucler (CYCLE
) si vous souhaitez épuiser le domaine complet.Cependant, il est assez utile pour la conversion d'entrée / sortie, comme votre migration depuis un autre SGBD. L'insertion de la valeur
2147483648
dans une colonne entière conduira à une " ERREUR: entier hors plage ", tandis que l'utilisation de l'expression2147483648::OID
fonctionne très bien.De même, lorsque vous sélectionnez une colonne entière sous forme de texte avec
mycolumn::TEXT
, vous obtiendrez des valeurs négatives à un moment donné, mais avecmycolumn::OID::TEXT
vous obtiendrez toujours un nombre naturel.Voir un exemple sur dbfiddle.uk .
la source