Functions must only accept input which they can properly act on.
A function serving web pages needs a different notion of String than a database function. There are Strings which are safe for a SQL use but unsafe to serve on a web page, and vice-versa.
Validation is restricting your input to only those things your function can act on.
I'm not saying SQLString is a bad idea. It's a good idea. I'm saying that the strategic advice to "validate input" didn't help you here, because to get to SQLString, you had to know specifically that there was a string-based SQL attack to mitigate. "Validate input" is like saying "know all possible bugs". Obviously, you should mitigate the bugs you know about! You just shouldn't pretend that telling someone to "validate input" is going to accomplish that. It's like telling people "don't have bugs".
For generalist developers who have to get things done: learn at least a little about the major classes of security vulnerabilities that impact your development environment, and select libraries designed to mitigate them.
For students: learn a lot about the most important classes of security vulnerabilities, of which memory corruption is one important example but just one, and then take the time to learn how to exploit at least simple variants of all of them in a realistic setting, to cultivate the mindset needed to think critically about software security.
Don't write anything in C. Sure. But really almost nobody does that anymore anyways.
But it's the typechecker's job to make sure you don't give an SqlCodeString to a function which takes a HtmlCodeString. Surely then a person writing such software isn't validating anything. So what should be validated?
Functions must only accept input which they can properly act on.
A function serving web pages needs a different notion of String than a database function. There are Strings which are safe for a SQL use but unsafe to serve on a web page, and vice-versa.
Validation is restricting your input to only those things your function can act on.