El marcador de posición mysql no funciona para DATE_ADD (perl)

I really appreciate your help on my last question. This is related but I didn't want to hide this question inside the other.. I'm having a problem using "DATE_ADD(NOW(), INTERVAL $interval)" inside a placeholder. Before I was using placeholders this line worked just fine, not it comes back as empty.

  $store = qq(INSERT INTO main (creator_name,relationship,time) VALUES(?,?,?) );

  my $sth = $dbh->prepare($store);
  $sth->execute($data{creatorname},$data{relationship}, "DATE_ADD(NOW(), INTERVAL $interval)");

Is there another way to add DATE_NOW so it's synatically proper? I tried adding it back in like

        $store = qq(INSERT INTO main (creator_name,relationship,time) VALUES(?,?, DATE_ADD(NOW(), INTERVAL $interval)) );

and it errored out saying the syntax was wrong. At least with the code on the top it executes, it just leaves the value empty. With this attempt it won't even try.

preguntado el 27 de noviembre de 13 a las 01:11

Hard to test a fix without knowing more about your setup, but at first glance it looks like you're mixing up SQL syntax and placeholder values. Tokens like DATE_ADD or NOW are SQL expressions, not variables. Each ? placeholder is a stand-in for exactly one scalar variable. As an example, DATE_ADD(NOW(), INTERVAL $interval) podría convertirse DATE_ADD(NOW(), INTERVAL ?) con $interval pasó a execute. Past that, I'm rusty on MySQL date functions, but do you need to specify units on that interval? -

@rutter, DATE_ADD(NOW(), INTERVAL ?) wouldn't work because the syntax is DATE_ADD(NOW(), INTERVAL {expr} {unit}). Podrías hacerlo DATE_ADD(NOW(), INTERVAL ? WEEK) pero no DATE_ADD(NOW(), INTERVAL ?) or DATE_ADD(NOW(), INTERVAL ? ?) -

2 Respuestas

Would you expect the following to print ABC?

$x = 'uc "abc"';
print $x;

No, that would make no sense. Same thing in SQL.

La cuerda DATE_ADD(NOW(), INTERVAL ...) is surely not a valid value for the time campo.

it errored out saying the syntax was wrong.

I'm pretty sure the message was more specific than that. You also didn't provide the value of $interval, without which we have no way of knowing what resulted in a syntax error.

respondido 27 nov., 13:02

The error is "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '". The variable $interval contains something in the form of "1 WEEK" or "1 MONTH". - aarón anderson

That would not be a syntax error, but I'll check tomorrow when I have access to MySQL to be sure. In the mean time, get the actual error message for us. - Ikegami

Changing your qq() to qq{} for clarity, this should be the fix:

$store = qq{
  INSERT INTO main (creator_name,relationship,time) 

my $sth = $dbh->prepare($store);

You'll need to change the word "SECOND" to the appropriate units, and $interval needs to be an integer.

Kudos for using prepared statements, but the reason why this doesn't work the way you tried it is very important: placeholders ? are not simply places where arbitrary text will be substituted into your query. This is why we make such a big deal about the importance of using prepared statements as one way to protect against sql injection. Placeholders are a hard delineation between "what is the query" and "what is the data" and they are sent to the server separately, not munged together.

Por lo tanto...

my $sth = $dbh->prepare(qq{SELECT * FROM user WHERE username = ? AND password = ?});
$sth->execute("hacker", "' OR 1 = 1; --");

...cannot be misinterpreted to become the dreaded...

SELECT * FROM user WHERE username = 'hacker' AND password = '' OR 1 = 1; --'

...when done in a prepared statement, as it would if you constructed your query with primitive string concatenation, because the server will never be confused between the two.

A placeholder substitutes exactly one scalar literal value, which "DATE_ADD(NOW(), INTERVAL $interval)" isn't. (Yes, it's a scalar string in Perl, but it contains an expression, not a literal value).

respondido 27 nov., 13:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.