My problem with state based solutions is they don't handle some scenarios. If I need to rename a table or column, that usually results in a drop and create - and you lose all your data (unless configured to fail on data loss - then the process fails). This is fairly common on our dev and test environments, but admittedly gets less frequent as we get closer to production.
A more troubling one is if you want to add a foreign key column to a table. Without a tool, you (1) Add the column [Allow nulls], (2) Populate the Column, (3) alter the column to NOT NULL and add the FK constraint. What I usually tell the developers is they need a Pre-Deploy script to do 1 & 2, and then we let the deployment tool take of 3. The Pre-Deployment script needs to be idempotent and we need a cleanup policy to remove the script after it's been deployed to all environments. Easy on paper, but with an environment having 100's of databases and 50+ developers - not easy to wrangle.
Factor in non-linear deployments (changesets A, B, & C are in UAT. B needs to go to prod tonight, but A & C have bugs and are going back to development) and now you no longer have a consistent artifact you can promote, but have to create something new and different that is going to run for the first time in production.
I always tell my developers that database deployments are hard because we can't just overwrite the server with all the current stuff like they do with code. DBA's have to consider the state of the data when the deploy is happening.