For non-technical people: If someone is building you a website, put a single backslash(and only that) in any text fields on your site. If it breaks when you submit, chances are good there is potential for SQL-injection. This is not a 100% check that will catch everything, heck it's not even a 70% check. But a poor programmer that doesn't know anything about SQL-injection will likely build code that fails this test.
What am I doing wrong?
As a sysadmin, this is interesting. I help out people who run WordPress sites, for instance. While I do my best, on a practical level not all of the code can be audited or rewritten.
As an SQL coder, this is interesting as he's cleverly crafting code in a language I've spent a fair amount of time playing with, and about which I would like to know more. It's interesting to see how someone might do SQL injection in the same way you might wonder how people pick padlocks, despite having no need to pick padlocks yourself.
Glad you liked the post =)
Even if you could solve all the code injection problems, what about Cross site Scripting? The list goes on...
1: You cannot call yourself a professional web developer. You can't even call yourself a competent amateur programmer, you are just playing with toys you clearly do not understand.
2: You deserve absolutely no pity when (not if) you get hacked.
If this sounds harsh, it's meant to, this is an incredibly well known problem (and has been for years) and it's incredibly easy to fix.
Prepared statements are about caching parsing and query planning and storing queries for future use, this gains performance and convenience but not necessarily security. You can use parametrized queries without storing them as prepared queries at the server. This is what Perl DBI, libpq (the C binding for PostgreSQL) and many others do.
In PostgreSQL you can use PREPARE and EXECUTE directly instead of through the convenience functions in your driver and be vulnerable to SQL injections. E.g.
PREPARE foo (boolean) AS SELECT $1;
EXECUTE foo (pg_terminate_backend(42)));Rule #1: Never trust the user.
If you are on Python, consider using SQLAlchemy or OurSQL. If you are on PHP, consider using Doctrine, Propel, or PDO.