-2

What would be more professional and error proof approach with simple mysql not PDO or anything

I usually do like this

    $sql_request = "SELECT * 
                      FROM myusers 
                          WHERE user_id = {$user_id} 
                            AND email = '{$email_address}' 
                              LIMIT 0,1";

However should i quote {$user_id} as well?

Even when i get user input i dont quote numbers, however i do check ctype_digit() before processing them.

John Smith
  • 681
  • 5
  • 13
  • 30
  • 5
    *professional and error proof approach with simple mysql* — That's something of a contradiction. The old mysql_* functions are deprecated. Don't use them. – Quentin Aug 31 '12 at 19:38
  • Its not the question i asked, but why should i not use {}? – John Smith Aug 31 '12 at 19:38
  • 1
    I personally do not quote numeric inputs, as I like for the code reader to be able to understand just by looking at the SQL query that the value is intended to be inserted into a numeric field. – Mike Brant Aug 31 '12 at 19:38
  • Quentin they not deprecated yet... i just cannot change entire website right now that i picked up from another developer, besides i think they ok if you use them properly. – John Smith Aug 31 '12 at 19:39
  • 4
    Quoting is one thing, but I certainly hope you are escaping your data, numeric or not! I'd recommend using prepared queries instead. – Brad Aug 31 '12 at 19:40
  • 3
    They have big red warnings saying not to use them in their manual pages. They might not have been removed but that is pretty good evidence of [deprecation](http://en.wikipedia.org/wiki/Deprecation). – Quentin Aug 31 '12 at 19:41
  • That solution is not as much simple as merely ancient. – Bugs Aug 31 '12 at 19:53
  • 1
    The solution is simple: **DO NOT USE** `mysql_query` or any of those functions. Period. They're dangerous in unskilled hands. You must use `mysqli`, PDO, or something equivalent to avoid extremely serious [SQL injection bugs](http://bobby-tables.com/php) that could destroy your application and/or your career. – tadman Aug 31 '12 at 20:04

7 Answers7

7

No, there's no need to place quotes around numeric literals.

With MySQL it's fine if the numeric literals are enclosed in single quotes; I think the reason we see it done so often is that it's convenient for programmers not to care about whether it's character or numeric, and just put quotes around all the literals.

There is a difference in behavior when a value is quoted and not quoted when the value is not a numeric literal. For example, given an id column of type INTEGER, in this context

... WHERE id = '1X'

The '1X' here will be interpreted as a literal numeric with a value of 1, but in this context

... WHERE id = 1X

The 1X here will be interpreted as a column name, rather than as a numeric literal. This will likely cause MySQL to throw an 'Unknown column' exception.

Consider the difference in how these will be interpreted...

... WHERE id = 'id'   -- 'id' will be interpreted as numeric literal value 0

... WHERE id = id     -- id will be interpreted as a column name

So it really boils down to which behavior is best for your application, when what you expect to be interpreted as a numeric literal is something other than numeric.


My personal preference is to NOT quote the numeric literals. This is probably due to my experience with other DBMSs and the need to avoid issues caused by implicit data conversions. My personal preference is also to use prepared statements, and avoid my statements including values as literals in the SQL text. (With MySQL that point is mostly moot, since a prepared statement with bind variables gets converted into plain SQL text when it's sent to the database... but that's done by the MySQL library, not my code. And again, this is preference is probably most informed by my longer experience using other RDBMSs (Oracle, Teradata, DB2, SQL Server) rather than MySQL itself.

spencer7593
  • 106,611
  • 15
  • 112
  • 140
2

I would strongly suggest to be carefull when quoting numerical values - here is what happened to me: An optimized, often-run query produced insane amounts of IO and quite some CPU laod:

SELECT blah FROM foo WHERE intcolumn='17';

with the selectivity being some 100 rows out of millions. I checked the execution plan: lo and behold, full table scan on the driving table. I checked the index on foo(intcolumn) again and again, even dropped and recreated it, no luck. Query time was in the minutes.

SELECT blah FROM foo WHERE intcolumn=17;

took less than 0.1 seconds. For some reason, MySQL had chosen to cast all foo.intcolumn to VARCHAR and then do a string compare to '17'. Ofcourse this included ignoring the index.

I don't know, if I hit an exotic bug in an old version of MySQL, bu I surely took away one thing: Make sure, the parser knows, what data type I intend to use. This ofocurse can be tricky with quoted numerals.

Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92
1

What would be more professional and error proof approach with simple mysql not PDO or anything

I'd say it is sprintf and writing readable code. You normally do not want to place the variable names into the strings but add them later based on order. That decouples it a bit more and is easier to read.

Also you can specify numeric data as %d so that you ensure it's an integer value and not prone to string injection. Numeric literals normally do not need quotes. So sprintf and SQL team up well here. %s needs quotes, %d does not. However quotes do not hurt either:

$sql_request = "SELECT * 
                  FROM myusers 
                      WHERE user_id = '%d'
                        AND email = '%s' 
                          LIMIT 0,1";

$query = sprintf($sql_request, $user_id, mysql_real_escape_string($email_address, $link));

However I read in your question about not mysqli or PDO. If you can, switch to PDO and use prepared statements / parametrized queries. If this is an old application, prefix the mysql_* functions with something and implement them your own based on PDO and slowly but steadily replace old with new code.

Also take a look at this question that should help you as well to start porting code, it works relatively quickly:

And for how to switch to PDO:

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • Anyone who considers themselves a professional developer wound **NEVER** use `sprintf` to do this kind of escaping any more than a professional doctor would never re-use a needle. The `sprintf` approach means you're just one missed escape call away from a SQL injection bug, and with those you expose yourself to enormous risk. – tadman Aug 31 '12 at 19:57
  • 1
    @tadman: Relax. You use these to have patterns for the queries, that's all. Has nothing to do with the actual escaping but to separate concerns and to establish configuration. That by the way helps to reduce complexity and offers a structured approach to problems which is professional. The doctor and needle picture you paint is a wrong one. What would be the needle here btw? – hakre Aug 31 '12 at 19:59
  • I would relax but the intersection of PHP and MySQL on Stack Overflow is a literal shop of horrors with such a casual attitude towards escaping and query construction. The answer is not to use `sprintf`, that's only obscuring the more serious problems and making it even harder to find mistakes. Placeholders, and only placeholders, provide an adequate level of safety. – tadman Aug 31 '12 at 20:08
  • @tadman: You can relax because this is not your code. I hope the OP is taking things seriously, that is far more important to press "the right thing to do" but without explaining why. Actually I'm quite happy that there is some real interest in understanding why because these are all the reasons why we in the end suggest to use PDO or the Mysqli extension. But we should still be able to explain why. And running around screaming "Wrong!" and not explaining anything is not very helpful in the end. So I have no problem to add my 2 cents on topic instead of only next to it. – hakre Aug 31 '12 at 20:14
  • Why is it that the PHP MySQL questions are created and answered by people with such a reckless disregard for proper SQL query construction? In the Python, Ruby or Java worlds there are libraries to do this properly and people *use* them. In PHP town I would guess maybe 10% of the questions involve a framework, PDO or `mysqli` and the problems these people are having are not escaping related. As ornery as I might sound, I'm just trying to put a stop to this nonsense. It's not even hard to use placeholders. There's very few excuses to use `sprintf` and this is not one. – tadman Sep 01 '12 at 02:42
  • @tadman: You must own the secret manual that has the pages about placeholders in the `mysql` extension. Would be better you would share them instead of barking the wrong tree. – hakre Sep 01 '12 at 09:26
  • That's why. That the original poster *wants* to use something not PDO means the only reasonable option is `mysqli` which *does* have placeholders. – tadman Sep 01 '12 at 22:03
  • No, you're wrong, the OP wants to use something `mysql` and *not* `mysqli`. So it is not an reasonable option at all, but just stupid to dictate that to the user. That won't make the planet any more safe. Also we're missing your answer here. – hakre Sep 02 '12 at 06:27
1

The common consensus is that it's not a good idea (i.e., not professional nor error-proof) to be writing SQL statements as an interpolated (your example) or concatenated string. You should use prepared statements instead.

In the dark ages, I used a function like:

// This is obsolete!!
function escape_input($s) {
  if (!ctype_digit($s))
    return "'" . mysql_real_escape_string($s) . "'";
  else
    return $s;
}

As you can see, I quoted string inputs, but allowed integer inputs to pass through without quotes. (Though you could quote integer inputs without any ill effects.) I used this function on every single MySQL input, regardless of whether I knew the input was an integer or not. By forcing myself to follow this pattern, I don't think I ever opened myself up to SQL injection attacks. But again, I would not do things this way anymore. I would use prepared statements from PDO or mysqli_*.

Stephen Booher
  • 6,522
  • 4
  • 34
  • 50
0

User_id column should not be quoted as it is numerical. But you have to make sure that numerical value is passed.

seeker
  • 3,255
  • 7
  • 36
  • 68
0

You don't need to quote $user_id as long as you make sure the variable contains a number.

If it doesn't it may break your query and even damage your database!

The better solution would be to use prepared statements using PDO or another library.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
-1

I would recommend on quoting. You can't never be too sure! (And you'd let MySQL handle the possible errors). Also, getting used to add quotes around your variables helps you to remember to always put them once you get used to it and makes do you less errors. (Don't forget to escape your inputs as well)

Or, use PDO or MySQLi with prepared statements! You won't even have to quote anymore. (Yeah, sorry. Answering to a question that really wants to use something that is deprecated makes me give better alternatives)

maaudet
  • 2,338
  • 4
  • 20
  • 28
  • Quoting isn't sure are all! If you quote this value and assign the value `'; drop table myusers; --` to $user_id, you will still be in trouble. :-) – GolezTrol Aug 31 '12 at 19:42
  • @GolezTrol That's not even related to the question. He is already checking if it's an integer in PHP before using it in the query. – maaudet Aug 31 '12 at 19:43
  • It is. If the value contains a number, you don't need to quote it. If you cannot be sure what value it contains, then quoting still isn't a solution. It only creates a false sense of safety because it will go wrong less often. So either treat it as a number or take real precautions. – GolezTrol Aug 31 '12 at 19:44
  • @GolezTrol What you state still isn't related to the question itself. – maaudet Aug 31 '12 at 19:46
  • If he is checking before if it is an integer, how does the `can't never be too sure` scenario play out? – AndrewR Aug 31 '12 at 19:46
  • What if, in the future, he removes the check by mistake? (And add escaping) – maaudet Aug 31 '12 at 19:46
  • If he removes the check by mistake, then he puts the database in danger, quoted or not. :) – GolezTrol Aug 31 '12 at 19:47
  • @GolezTrol You're still out of context. We're not talking about escaping at all but quoting. – maaudet Aug 31 '12 at 19:48
  • Don't you see it? Your answer 'I would recommend on quoting. You can't never be too sure!' doesn't make sense. If it's a number, there's absolutely no reason to use quotes. If it's not, escaping does become relevant. – GolezTrol Aug 31 '12 at 19:50
  • Wait, are you mixing up curly brackets and quotes? – GolezTrol Aug 31 '12 at 19:51
  • @GolezTrol I'm not mixing up anything. I understand your statement, but it is not related to the question. He wants other people's input about why or not to add quotes when it's not required. This is my answer. – maaudet Aug 31 '12 at 19:52
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/16113/discussion-between-goleztrol-and-manhim) – GolezTrol Aug 31 '12 at 19:55