I am implementing a RESTful web service that accesses a database. Entities in the database are versioned to detect multiple updates. For instance, if the current value is
The appropriate thing to do is always to follow the HTTP spec if you're using HTTP, and the reason is simply to allow people who understand the spec to function correctly.
412 should only be used if a precondition (e.g. If-Match) caused the version matching to fail, whereas 409 should be used if the entity would cause a conflict (the HTTP spec itself alludes to this behaviour in the definition of 409).
Therefore, a client that doesn't send ETags won't be expecting a 412. Conversely, a client that does send ETags won't understand that it's ETags that are causing a 409.
I would stick with one way. You say that "the database schema can't change", but that doesn't stop you (right in the HTTP server layer) to extract the version from the datbase representation and put it in the ETag, and then on the way in, take the If-Match header and put it back in the version field.
But doing it completely in the entity body itself isn't forbidden. It just requires you to explain the concept and how it works, whereas with the ETag solution you can just point people to the HTTP spec.
Edit: And the version flag doesn't have to be a hash of the current resource; a version is quite acceptable. ETag: "3"
is a perfectly valid ETag.