Lorsque vous dites "toutes les bases de données ne le prennent pas en charge", je pense qu'une meilleure façon de le dire est la suivante:
Chaque base de données principale prend en charge cela, car elle prend largement en charge les déclencheurs, les fonctions et d'autres fonctionnalités avancées.
Cela nous amène à la conclusion que cela fait partie du SQL avancé et a du sens à un moment donné.
Do people actually use domains in their database designs?
Le moins possible, en raison de la couverture étendue requise (compte tenu des opérateurs, des index, etc.)
If so to what extent?
Encore une fois, aussi limité que cela puisse être, si un type existant combiné à un peu de logique définie supplémentaire (par exemple des contrôles, etc.) peut faire l'affaire, pourquoi aller aussi loin?
How useful are they?
Beaucoup. Considérons une seconde un SGBD pas si bon que MySQL, que j'ai choisi pour cet exemple pour une raison: il manque un bon support pour le type inet (adresse IP).
Maintenant, vous voulez écrire une application qui se concentre principalement sur les données IP comme les plages et tout cela, et vous êtes coincé avec le type par défaut et ses fonctionnalités limitées, vous allez soit écrire des fonctions et des opérateurs supplémentaires (comme ceux pris en charge nativement dans postgreSQL pour exemple) ou écrivez des requêtes beaucoup plus complexes pour chaque fonctionnalité dont vous avez besoin.
Il s'agit d'un cas où vous justifierez facilement le temps passé à définir vos propres fonctions (inet >> inet dans PostgreSQL: plage contenue dans l'opérateur de plage).
À ce stade, vous avez déjà justifié l'extension de la prise en charge du type de données, il n'y a qu'une autre étape pour définir un nouveau type de données.
Revenons maintenant à PostgreSQL qui a un support de type vraiment sympa mais sans int. Non signé dont vous avez besoin, car vous êtes vraiment préoccupé par le stockage / les performances (qui sait ...), vous devrez l'ajouter ainsi que le opérateurs - bien que cela dérive principalement des opérateurs int existants.
What pitfalls have you encountered?
Je ne joue pas avec ça car jusqu'à présent, je n'ai pas eu de projet qui exigeait et justifiait le temps requis pour cela.
Le plus gros problème que je peux voir venir serait de réinventer la roue, d'introduire des bogues dans la couche "sûre" (db), un support de type incomplet que vous ne réaliserez que des mois plus tard lorsque votre CONCAT (cast * AS varchar) échoue parce que vous n'a pas défini de cast (newtype comme varchar), etc.
Il y a des réponses qui parlent de "peu commun" etc. Certainement celles-ci sont et devraient être rares (sinon cela signifie que le dbms manque de beaucoup de types importants), mais d'un autre côté, il faut se rappeler qu'un (bon) db est conforme ACID ( contrairement à une application) et que tout ce qui concerne la cohérence y est mieux conservé.
Il existe de nombreux cas où la logique métier est gérée dans la couche logicielle et cela peut être fait en SQL, où c'est plus sûr. Les développeurs d'applications ont tendance à se sentir plus à l'aise au sein de la couche application et évitent souvent de meilleures solutions implémentées dans SQL, cela ne doit pas être considéré comme une bonne pratique.
Les UDT peuvent être une bonne solution pour l'optimisation, un bon exemple est donné dans une autre réponse sur le type m / f en utilisant char (1). S'il s'agissait d'un UDT, ce pourrait être un booléen à la place (sauf si nous voulons offrir les troisième et quatrième options). Bien sûr, nous savons tous que ce n'est pas vraiment une optimisation en raison de la surcharge de la colonne, mais la possibilité est là.