简体   繁体   中英

MySQL query, comparing datetime

In my page user can register with email and subscribe for news. I'm putting email, IP and timestamp into my database. I want to make sure that one IP can only get 5 emails per day and I don't want the same email addresses in my database.

I tried this but it doesn't work, I can post as many as I want.

if(isset($_POST["send"]))
{
    $email = test_input($_POST['email']);
    if (!filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
    $query = 'INSERT INTO subscriber (data, ip, email) (SELECT CURRENT_TIMESTAMP, "'.$_SERVER['REMOTE_ADDR'].'", "'.$email.'" FROM dual where NOT EXISTS ( Select count(email) as c  FROM (
    SELECT email FROM subscriber  WHERE ip="'.$_SERVER['REMOTE_ADDR'].'" and DATE(`data`) = CURDATE() group by email) as a having c>5))';
    $result =  mysqli_query($dbc, $query) or die(mysqli_error($dbc));
    $msg="E-mail sent successfully";
} else
{
    $msg="Wrong e-mail address";
}

And not to write same emails i should use something like this after insert?

FROM dual WHERE NOT EXISTS ( SELECT * FROM subscriber WHERE email="'.$email.'" )';

Why don't you just separate the queries. First check for

SELECT count(id) FROM subscriber  
WHERE ip="'.$_SERVER['REMOTE_ADDR'].'" 
and DATE(`data`) = CURDATE()

And if the result is < 5 then do the insert. It will be simple and readable.

The whole code:

if(isset($_POST["send"])){

$email = test_input($_POST['email']);
if (!filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
    $query = 'SELECT count(id) FROM subscriber  
              WHERE ip="'.$_SERVER['REMOTE_ADDR'].'" 
              and DATE(`data`) = CURDATE()';
    $result =  mysqli_query($dbc, $query);
    $count  = mysqli_fetch_field($result);

    if($count < 5) {
        $query = "SELECT id FROM subscriber  
                  WHERE email='".$email."'
                  LIMIT 1";
        $result =  mysqli_query($dbc, $query);
        $mailExist = mysqli_num_rows($result);

        if($mailExist > 0) {
            $msg="E-mail is already existing in the DB";
        }
        else {
            $query = "INSERT INTO subscriber (data, ip, email) VALUES (CURDATE(), '".$_SERVER['REMOTE_ADDR']."', '".$email."')";
            mysqli_query($dbc, $query);
            $msg="E-mail sent successfully";
        }
    }
    else {
        $msg="5 emails today";
    }
}
else {
    $msg="Wrong e-mail address";
}

It will be good if you put indexes on this fields in DB. But I will advise you to use PDO instead of mysqli. You can read more about it here http://php.net/manual/en/book.pdo.php

You should not GROUP BY email, when you want to count all emails from the same IP.

So your fixed query would be:

INSERT INTO subscriber (data, ip, email)
    SELECT CURRENT_TIMESTAMP, {$_SERVER['REMOTE_ADDR']}, {$email} 
    FROM dual 
    where NOT EXISTS (
        Select count(email) as c  
        FROM (
            SELECT email
            FROM subscriber  
            WHERE ip={$_SERVER['REMOTE_ADDR']} 
              and DATE(`data`) = CURDATE() 
        ) as a 
        having c>=5
    )

You can also write it another way

INSERT INTO subscriber (data, ip, email)
    SELECT CURRENT_TIMESTAMP, {$_SERVER['REMOTE_ADDR']}, {$email} 
    FROM dual 
    where NOT EXISTS (
        Select count(email) as c  
        FROM subscriber  
        WHERE ip={$_SERVER['REMOTE_ADDR']} 
          and DATE(`data`) = CURDATE() 
        having c>=5
    )

Or this way:

INSERT INTO subscriber (data, ip, email)
    SELECT CURRENT_TIMESTAMP, {$_SERVER['REMOTE_ADDR']}, {$email} 
    FROM dual 
    where 5 < (
        Select count(email) as c  
        FROM subscriber  
        WHERE ip={$_SERVER['REMOTE_ADDR']} 
          and DATE(`data`) = CURDATE() 
    )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM