There are several different "flavors" of constraint. Some of them have to do with referential integrity, some have to do with uniqueness, some have to do with ranges of or lists of valid values, some have to do with defaults. Each has a use, but the bottom line is that they are for properly defining the way data in the problem space fits together. Note that I am talking here about defining a constraint as a LOGICAL database design activity, not as a PHYSICAL database implementation activity.
Now, when you actually create tables in some DBMS from your design, you may choose to only SELECTIVELY implement your constraints. There are many reasons for implementing or not implementing any particular constraint. Some examples of this are performance impact, replication, the importance of data integrity in your app, where you enforce ranges, etc. Those decisions all have trade-offs, which I don't really want to get into in this limited space. Maybe I'll write a book. ;)