yes you are quite right. But IMO dynamic SQL is hugely overused and the first solution of choice, and IMHO avoiding the Security (Now we have Dyanmic SQL we just need to GRANT SELECT, UPDATE, DELETE on ALL Tables to ALL Users ), SQL Injection risks, etc. is best achieved by finding ways to avoid using Dynamic SQL in the first place.
I think that use of EXECUTE AS and having Certificates for proxy execution are pretty advanced approaches and probably not realistic for the skill-set for the average developer who is using Dynamic SQL to work around a "snag". Hence "Don't use dynamic SQL" is my first solution advice.
For anyone who has the skills to use the safety nets then Dynamic SQL presents no threat. But making sure that non-SQL developers write safe SQL? I doubt that training them up to include all that stuff is realistic. Look at the proliferation of NOLOCK - most 3rd party code I encounter has been written using the "get it done" method
Using sp_ExecuteSQL and parameterising all dynamic SQL is a good place to start (and has the advantage of cached query plans / reuse), but sooner or later a @TableName, @ColumnName or an @IN_List creeps in and bypasses the SQL Injection safety.
Surely Dynamic SQL is most commonly used for a Table or Column substitution in the SQL, or an IN list? When those questions come up here usually there are alternative programming solutions that avoid dynamic SQL ... hence my view is to recommend "Avoid dynamic SQL" as a first principle.
I've probably overlooked all sorts of real world examples of where Dynamic SQL IS the solution?