Problem is, that is too limiting to satisfy the functional use cases in a lot of code that constructs SQL queries by substituting values into templates, where some of the pieces are necessarily dependent on inputs from logged-in users and such.
let _rows = sql_query("SELECT * FROM users WHERE username=?", &[username]);
The statement is static, but the [username] part is not, it's just a variable that can have whatever username you want.
They're saying injection attacks come from dynamically building strings, so if you prevent that you stop the vulnerabilities.
The argument isn't "block ' characters to stop SQL injection" it's "force the developer to use prepared statements and no dynamically constructed queries".
Second, the naive and silly attacks are the default definition of SQL injection -- and the most commonly found holes, so even if it just prevented those that would be still a huge help. Nothing statically ensures that at runtime except the programmer's due diligence.