To build on what cpradio has already said, when designing your error handling protocols, be mindful that there is a small overhead (however minimal) while instantiating and handling the exception. How much this hurts the performance of your code would entirely depend on the complexity of said code.
If you are bubbling up through several layers of exceptions, passing the previous exception into each new one, then you could run in to less maintainable code, and somewhat less understandable error reports. In most cases, you are going to want to halt execution on the very first true error. In such cases, only a top level try-catch will do the trick.
If you find yourself using them as a means to control program flow, by testing the success of a method, you would be better off testing bool returns and exiting, or controlling the flow in a more formal manner. Using exceptions to notify the user that some method failed is inefficient and considered bad practice.
Remember that some libraries already have an exception subclass they throw when a method fails anyway. The trick here is to read up on those libraries and catch the error by type.
// tried code
catch (PDOException pdoException)
// handle pdo exceptions one way
catch (Exception exception)
// handle everything else another way
My advice would be to start off at the highest level possible and only introduce deeper exceptions if a true, deeper need arises.
In your case, you probably don't want to introduce layered try-catch blocks. However, it may be to your benefit to subclass PDOException into PDOFetchException and PDOQueryException and throw these, letting the top level handler do the work. In this way, you consolidate exception processing without loosing the specific nature you desire. PDOStatement::Execute, for example, returns a bool (as most pass/fail methods do). Test this value and merely raise your subclassed exception.