Когда вы говорите «не все базы данных поддерживают это», я думаю, что лучший способ выразить это так:
Все основные базы данных поддерживают это, поскольку они поддерживают триггеры, функции и другие расширенные функции.
Это приводит нас к выводу, что это часть продвинутого SQL и имеет смысл в какой-то момент.
Do people actually use domains in their database designs?
Наименее возможный из-за необходимого широкого охвата (с учетом операторов, индексов и т. Д.)
If so to what extent?
Опять же, настолько ограниченно, насколько это возможно, если существующий тип в сочетании с небольшой дополнительной определенной логикой (например, проверки и т. Д.) Может добиться цели, зачем идти так далеко?
How useful are they?
Много. Давайте на секунду рассмотрим не очень хорошую СУБД, такую как MySQL, которую я выбрал для этого примера по одной причине: ей не хватает хорошей поддержки для типа inet (IP-адрес).
Теперь вы хотите написать приложение, которое в основном ориентировано на данные IP, такие как диапазоны и все такое, и вы застряли с типом по умолчанию и его ограниченной функциональностью, вы либо напишите дополнительные функции и операторы (например, те, которые изначально поддерживаются в postgreSQL для пример) или напишите гораздо более сложные запросы для каждой функциональности, которая вам нужна.
Это тот случай, когда вы легко сможете оправдать время, потраченное на определение ваших собственных функций (inet >> inet в PostgreSQL: диапазон, содержащийся в операторе range).
К этому моменту вы уже оправдали расширение поддержки типов данных, есть только один шаг к определению нового типа данных.
Теперь вернемся к PostgreSQL, который имеет действительно хорошую поддержку типов, но не имеет беззнакового типа int, который вам нужен, потому что вы действительно заботитесь о хранилище / производительности (кто знает ...), так что вам нужно добавить его, а также операторы - хотя, конечно, это в основном вывод существующих операторов int.
What pitfalls have you encountered?
Я не балуюсь этим, так как до сих пор у меня не было проекта, который требовал и оправдывал время, необходимое для этого.
Самая большая проблема, с которой я могу столкнуться, это переизобретение колеса, внесение ошибок в «безопасный» слой (db), поддержка неполного типа, которую вы поймете только через несколько месяцев, когда ваш CONCAT (cast * AS varchar) завершится неудачно, потому что вы не определили приведение (newtype как varchar) и т. д.
Есть ответы, говорящие о «необычном» и т. Д. Определенно, они есть и должны быть необычными (в противном случае это означает, что в dbms отсутствует много важных типов), но с другой стороны, следует помнить, что (хороший) db совместим с ACID ( в отличие от приложения) и что все, что связано с согласованностью, лучше хранить там.
Во многих случаях бизнес-логика обрабатывается на программном уровне, и это может быть сделано в SQL, где это безопаснее. Разработчики приложений, как правило, чувствуют себя более комфортно на уровне приложений и часто избегают лучших решений, реализованных в SQL, это не должно рассматриваться как хорошая практика.
UDT могут быть хорошим решением для оптимизации, хороший пример приведен в другом ответе о типе m / f с использованием char (1). Если бы это был UDT, он мог бы быть логическим (если мы не хотим предлагать третий и четвертый варианты). Конечно, мы все знаем, что это не совсем оптимизация из-за накладных расходов столбца, но такая возможность есть.