2

過去 XX 分間にログインしたユーザーのリストを提供するために、PHP と PDO を使用して作成している SELECT ステートメントがあります。時間間隔をハードコーディングすると、SQL ステートメントが正常に実行されますが、Web フォームから選択した間隔を代用しようとすると、SQL エラーが発生します。何が悪いのかわかりません。PDO と PREPARE ステートメントを使用しています

try
{
    $sql = 'SELECT DISTINCT PlayerName 
        FROM Player_Data pd LEFT JOIN character_data cd 
        ON pd.PlayerUID = cd.PlayerUID 
        WHERE cd.LastLogin > DATE_SUB(NOW(), :login_interval_value)';
    $statement = $pdo->prepare($sql);
    $statement->bindValue(':login_interval_value',$_POST['login_interval']);
    $statement->execute();
    $results = $statement->fetchAll();
}
catch (PDOException $e)
{
    $error = 'Error getting player names: ' . $e->getMessage();
    include 'error.html.php';
    exit();
}

これは私が得るエラーです...

Error getting player names: SQLSTATE[42000]: Syntax error or access violation: 1064 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 ''INTERVAL 60 MINUTES')' at line 4
4

2 に答える 2

4

二箇所訂正。時間単位は特異です(1)。もう 1 つは、login_interval の投稿データを分数にする必要があることです。これは完全に合法です:

DATE_SUB(NOW(), INTERVAL '60' MINUTE)

これは正しくなく、投稿データが間隔式全体である場合に発生します。

DATE_SUB(NOW(), 'INTERVAL 60 MINUTE')

$_POST['login_interval'] が単なる分数になるようにフォームを変更するか、そこから数値を抽出します。フォームを変更すると、コードは次のように変更されます。

try
{
    $sql = 'SELECT DISTINCT PlayerName 
        FROM Player_Data pd LEFT JOIN character_data cd 
        ON pd.PlayerUID = cd.PlayerUID 
        WHERE cd.LastLogin > DATE_SUB(NOW(), INTERVAL :login_interval_value MINUTE)';
    $statement = $pdo->prepare($sql);
    $statement->bindValue(':login_interval_value',$_POST['login_interval']);
    $statement->execute();
    $results = $statement->fetchAll();
}

1 - https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-add

于 2013-05-29T01:27:16.950 に答える
1

にプレースホルダーを使用することはできませんINTERVAL 60 MINUTES。引用されます。

値を整数にキャストするだけです(代わりに番号を投稿してください)。

$sql = 'SELECT DISTINCT PlayerName 
    FROM Player_Data pd LEFT JOIN character_data cd 
    ON pd.PlayerUID = cd.PlayerUID 
    WHERE cd.LastLogin > DATE_SUB(NOW(), INTERVAL '.(int)$_POST['login_interval'].' MINUTES)';
$statement = $pdo->prepare($sql);
$statement->execute();
$results = $statement->fetchAll();
于 2013-05-29T01:18:48.507 に答える