I have to mention the problems with DRY in the relational database world. Databases are designed to perform quickly and well using set-based logic and through sargable queries. DRY principles often cause the developer to write non-Sargable queries or use Row-by-agonizing-Row logic to leverage existing code in multiple situations. DRY and performance optimization are often at odds and in the database world, performance is usually far more critical than maintainabilty. This doesn't mean that you should not use DRY principles at all, just that you should be aware of how it will affect the overall usability of the database. Application developers thing DRY first and performance second, database developers think data integrity first, performance second,security of the data third(performance and security might swap places in some systems). Maintainibilty and thus DRY is a far distant 4th.
I've noticed in general, that the more layers of abstraction you put into database queries the slower they become. I'm not saying I didn't wish the people who design the datbase programs themselves didn't do a better job of allowing developers to use DRY without affecting how well the database performs, but I don't design database software at that level, so perhaps the conflict between abstraction and performance in database is harder to fix than I suppose. However, we have to work with the systems as they are currently built. We can ask for better implementation of DRY principles in future releases that won't also kill performance (and it has gotten better through the years but is still problematic), but in the meantime we must consider if DRY is the right move for this database at this time.
But often the very features that you want to use to ensure the DRY principle is met are the ones that cause tremendous problems for the database. I'm not saying never use DRY but don't go overboard with it.
Examples of what I'm talking about. You need to do a data import of a million records once a month. Records can already be manually added through the user interface calling a stored proc. This proc, because it was designed for single record imports, only adds one record at a time. Using DRY to avoid having the insert code in two places, you write a cursor to call the proc repeatedly rather than write the set-based imports you need. Time for the import goes from the 30 minutes it would take using set-based logic to 18 hours. Now the right way to adhere to DRY in this case would be to fix the proc to handle mulitple record imports. Unfortunately, it is often impossible or very difficult to send an array to a proc (depending on the db back end) and by changing the proc, you end up breaking the application.
Scalar functions and table-valued functions are also used to implement DRY principles and again they can seriously affect performance especially if you need to use them in a way that prevents the indexes from being useful.
Views are also good for implementing DRY. However, if you implement DRY through the use of views that call views that call other views, you will quickly get to the point where the queries will timeout under load. In fact you might end up needing to generate data sets of millions of records when you only need three at the end. So a one-level view of a complex set of joins to implement DRY can be excellent (I have one myself that we use to make sure all financial reporting uses the same base set of tables and calculations of certain things), more than two levels and you need to consider if you are creating a performance mess.