How to insert things like “now() -interval '2 minutes'” into PHP PDO query?

后端 未结 4 1193
无人共我
无人共我 2021-01-11 20:14

I have a query like this: (on Postgresql 8.4, PHP-fpm 5.3.10 (fpm-fcgi))

select * from users where now() - interval \'2 minutes\' < seenlast ORDER BY seen         


        
相关标签:
4条回答
  • 2021-01-11 20:30
    ... - INTERVAL :myminute MINUTES ...
    

    without the quotes is the proper method. If it helps, think of the placeholders as the equivalent of use old-school variable-based query building methods

    ... - INTERVAL $myminute MINUTES
    

    except the placeholders take care of the injection vulnerabilities that the variables don't. Just because you're using placeholders doesn't mean you can change SQL syntax, so

    ... - INTERVAL '2 minutes'
    ... - INTERVAL ':myminute minute'
    

    are not valid SQL.


    followup for mu:

    mysql> select now() + interval '2 minute';
    ERROR 1064 (42000): 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 '' at line 1
    mysql> select now() + interval 2 minute;
    +---------------------------+
    | now() + interval 2 minute |
    +---------------------------+
    | 2013-01-22 13:38:24       |
    +---------------------------+
    1 row in set (0.02 sec)
    
    0 讨论(0)
  • 2021-01-11 20:45

    I don't know much PDO or PHP but I think I know what's going wrong here.

    When you say this:

    interval '3 minutes'
    

    You're really performing a cast operation that's the same as:

    '3 minutes'::interval
    cast('3 minutes' as interval)
    

    So what you're doing is casting a TEXT value to an INTERVAL. That means that you need to produce something that looks like the string '3 minutes'. You could paste the string pieces together using string concatenation:

    # Use cast to make the precedence cleaner.
    $query = $db_conn->prepare("select * from users where now() - cast(:myminute || ' minutes' as interval) < seenlast ORDER BY seenlast"); 
    $query->bindParm(":myminute", $mymin)
    

    Or you should be able to do the string wrangling in PHP:

    $query = $db_conn->prepare("select * from users where now() - interval :myminute < seenlast ORDER BY seenlast"); 
    $query->bindParm(":myminute", $mymin . ' minutes')
    
    0 讨论(0)
  • 2021-01-11 20:54

    I have been struggling with Phalcon and its inner Models PDO parser for hours with the same problem.

    I found this solution:

    public static function getTimedoutRequests($secsThreshold) {
        return self::find(
            array(
                // PDO is buggy here, can't use INTERVAL
                "DATE_PART('epoch', create_time) < DATE_PART('epoch', NOW()) - ?0",
                "bind" => array(
                    $secsThreshold
                )
            )
        );
    }
    
    0 讨论(0)
  • 2021-01-11 20:57

    Intervals can be multiplied by numbers. So one approach to this is to prepare the statement saying interval '1 minute' * :myminutes instead, passing the "myminutes" parameter as a simple integer.

    0 讨论(0)
提交回复
热议问题