The best way is always using parameters. Those handle everything for you and you don't need to do any escaping.
If you can't use parameters, you have to do the encoding yourself, and that's very tricky. One way would be to use a format you can encode safely - for example, instead of inserting as a string literal, you might use binary encoding (eg. cast(0xAABBCCDD as varchar(max))
). This is perfectly safe, since you can be sure that there's no invalid character that would break it. Of course, it also has its problems.
As for your example, replacing '
with ''
works fine (although of course you'd have to watch out for other invalid characters, such as endlines). Your problem is that you didn't do the encoding on all the strings. In your sample, the last string has the proper encoding, the one before it does not. This also beautifully illustrates the pain of making sure you're encoding properly - and everything you miss means an error, or even a way to exploit the code and cause harm. For example, what if the description was ', ''0'', ''NULL''); delete from users --
?