I had a really good answer to my question Using CASE to select between two geometry functions? but a problem arises if there are more than one lake in a forest; then the solution returns multiple forests.
Let me rephrase the question in much more general terms.
Problem
I have some forest polygons, and some lake polygons, in separate tables (layers) in PostgreSQL. I want to use PostGIS/PostgreSQL to create a new table with forests, that have holes where the lakes are.
Some forests have many lakes, some have one, and many have none. I expect the number of output forests to be the same as the input forests (except if a forest is actually cut entirely by a lake).
I need to preserve an ID-number attribute on the forests.
Best Answer
This is essentially the same as the other answers, however if you are dealing with larger tables and cutting lakes out of many forests you may want to try this variation.
It should take advantage of spatial indexes and only union together lakes that need to be used as a cutter.
I've done this as a select (with a CTE to provide sample data)