简体   繁体   English

UPDATE表记录而不是添加新记录MySQL

[英]UPDATE table record instead of adding a new record MySQL

Ok .. Here is the thing. 好的..这是东西。 I want to list users logged on and change their status when logged out. 我想列出已登录的用户,并在注销后更改其状态。 This works perfect. 这完美。 I created a table for that called tblaudit_users. 我为此创建了一个名为tblaudit_users的表。 The existing users I SELECT from a tbl_users table. 我从tbl_users表中选择的现有用户。

What I want, is that if an user already exists in the tblaudit_users table it will UPDATE the LastTimeSeen time with NOW(). 我想要的是,如果tblaudit_users表中已经存在一个用户,它将使用NOW()更新LastTimeSeen时间。 But instead of updating that record, it creates a new record. 但是,它没有更新该记录,而是创建了一条新记录。 This way the table will grow and grow and I want to avoid that. 这样,桌子会越来越大,我想避免这种情况。 The code I use for this looks like: 我为此使用的代码如下所示:

+++++++++++++++++++ +++++++++++++++++++

$ipaddress = $_SERVER['REMOTE_ADDR'];

if(isset($_SESSION['id'])){

    $userId = $_SESSION['id'];
    $username = $_SESSION['username'];
    $achternaam = $_SESSION['achternaam'];
    $district = $_SESSION['district'];
    $gemeente = $_SESSION['gemeente'];

    $query = $db->prepare("SELECT * FROM tblaudit_users WHERE username = '{$username}' AND active = '1' LIMIT 1");
    $query->execute();

    foreach($query->fetchAll(PDO::FETCH_OBJ) as $value){
        $duplicate = $value->username;  
    }

    if($duplicate != 1){

        $insert = $db->prepare("
                    INSERT INTO tblaudit_users (user_id, username, achternaam, district, gemeente, ipaddress, LastTimeSeen, status)
                    VALUES ('{$userId}', '{$username}', '{$achternaam}', '{$district}', '{$gemeente}', '{$ipaddress}', NOW(), '1')
                    ");
        $insert->execute();

    } elseif($duplicate = 1){

        $update = $db->prepare("UPDATE tblaudit_users SET LastTimeSeen = NOW(),status = '1' WHERE username = '{$username}'");
        $update->execute();

    } else {
        header('Location: index.php');
        die();
    }
}

I am lost and searched many websites/pages to solve this so hopefully someone here can help me? 我迷路了,搜寻了许多网站/页面来解决这个问题,所以希望这里有人可以帮助我? Thanks in advance !! 提前致谢 !!

UPDATE: 更新:

I've tried the below with no result. 我已经尝试了以下方法,但没有结果。

+++++ +++++

$insert = $db->prepare("
                    INSERT INTO tblaudit_users (user_id, username, achternaam, district, gemeente, ipaddress, LastTimeSeen, status)
                    VALUES ('{$userId}', '{$username}', '{$achternaam}', '{$district}', '{$gemeente}', '{$ipaddress}', NOW(), '1')
                    ON DUPLICATE KEY UPDATE set LastTimeSeen = NOW(), status = '1'
                    ");
        $insert->execute();

Ok. 好。 I altered my query and code a little: 我更改了查询和代码:

$query = $db->prepare("SELECT * FROM tblaudit_users WHERE username = '{$username}' LIMIT 1");
$query->execute();

if($query){

    $insert = $db->prepare("
                INSERT INTO tblaudit_users (user_id, username, achternaam, district, gemeente, ipaddress, LastTimeSeen, status)
                VALUES ('{$userId}', '{$username}', '{$achternaam}', '{$district}', '{$gemeente}', '{$ipaddress}', NOW(), '1')
                ON DUPLICATE KEY UPDATE set LastTimeSeen = NOW(), status = '1'
                ");
    $insert->execute();

} else {
    header('Location: index.php');
    die();
}

} }

I also added a UNIQUE key called pid (primary id). 我还添加了一个称为pid(主ID)的UNIQUE密钥。 Still not working. 还是行不通。

Base on http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html , don't use 'set' in update syntax 基于http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html ,请勿在更新语法中使用'set'

example from the page: 页面中的示例:

INSERT INTO table (a,b,c) VALUES (4,5,6) ON DUPLICATE KEY UPDATE c=9;

Several issues: 几个问题:

  • You test on $query , but that is your statement object, which also will be valid even if you have no records returned from the select statement; 您在$query上进行测试,但这是您的语句对象,即使您没有从select语句返回的记录,该对象也将有效。
  • There can be issues accessing a second prepared statement before making sure the previous one is closed or at least has all its records fetched; 在确保关闭前一条语句或至少获取其所有记录之前,访问第二条准备好的语句可能会遇到问题;
  • There is a syntax error in the insert statement ( set should not be there); insert语句中有语法错误( set不应该存在);
  • For the insert ... on duplicate key update to work, the values you provide must include the unique key; 为了使insert ... on duplicate key updateinsert ... on duplicate key update生效,您提供的值必须包含唯一键;
  • SQL injection vulnerability; SQL注入漏洞;
  • Unnecessary split of select and insert : this can be done in one statement selectinsert不必要的分割:这可以在一个语句中完成

You can write your test using num_rows() . 您可以使用num_rows()编写测试。 To get a correct count call store_result() . 要获取正确的计数,请调用store_result() Also it is good practice to close a statement before issuing the next one: 同样好的做法是在发出下一个语句之前先关闭一条语句:

$query = $db->prepare("SELECT * FROM tblaudit_users 
                       WHERE username = '{$username}' LIMIT 1");
$query->execute();
$query->store_result();
if($query->num_rows()){
     $query->close();
     // etc...

However, this whole query is unnecessary when you do insert ... on duplicate key update : there is no need to first check with a select whether that user actually exists. 但是,当您insert ... on duplicate key update时,整个查询是不必要的:无需先进行select检查该用户是否实际存在。 That is all done by the insert ... on duplicate key update statement. 这全部由insert ... on duplicate key update语句insert ... on duplicate key updateinsert ... on duplicate key update完成。

Error in INSERT INSERT错误

The syntax for ON DUPLICATE KEY UPDATE should not have the word SET following it. ON DUPLICATE KEY UPDATE的语法后面不应带有单词SET

Prevent SQL Injection 防止SQL注入

Although you use prepared statements (good!), you still inject strings into your SQL statements (bad!). 尽管您使用准备好的语句(好!),但仍将字符串插入SQL语句中(坏!)。 One of the advantages of prepared statements is that you can use arguments to your query without actually injecting strings into the SQL string, using bind_param() : 准备好的语句的优点之一是,您可以使用bind_param()来在查询中使用参数,而无需将字符串实际注入SQL字符串中:

$insert = $db->prepare("
    INSERT INTO tblaudit_users (user_id, username, achternaam, district, 
                                gemeente, ipaddress, LastTimeSeen, status)
    VALUES (?, ?, ?, ?, ?, ?, NOW(), '1')
    ON DUPLICATE KEY UPDATE LastTimeSeen = NOW(), status = '1'
    ");
$insert->bind_param("ssssss", $userId, $username, $achternaam, 
                              $district, $gemeente, $ipaddress);
$insert->execute();

This way you avoid SQL injection . 这样可以避免SQL注入

Make sure that user_id has a unique constraint in the tblaudit_users . 确保user_idtblaudit_users具有唯一约束。 It does not help to have another (auto_increment) field as primary key. 将另一个(auto_increment)字段用作主键是没有帮助的。 It must be one of the fields you are inserting values for. 它必须是您要为其插入值的字段之一。

The above code no longer uses $query . 上面的代码不再使用$query You don't need it. 不用了

I found the issue 我发现了问题

if(isset($_SESSION['id'])){

    $userId = $_SESSION['id'];
    $username = $_SESSION['username'];
    $achternaam = $_SESSION['achternaam'];
    $district = $_SESSION['district'];
    $gemeente = $_SESSION['gemeente'];

    $query = $db->prepare("SELECT * FROM tblaudit_users WHERE user_id = '{$userId}' LIMIT 1");
    $query->execute();

    if($query->rowcount()<1){

      $insert = $db->prepare("
                  INSERT INTO tblaudit_users (user_id, username, achternaam, district, gemeente, ipaddress, LastTimeSeen, status)
                  VALUES ('{$userId}', '{$username}', '{$achternaam}', '{$district}', '{$gemeente}', '{$ipaddress}', NOW(), '1')
                  ");
      $insert->execute();

    } elseif($query->rowcount()>0) {

        $update = $db->prepare("UPDATE tblaudit_users SET LastTimeSeen = NOW(),status = '1' WHERE user_id = '{$userId}'");
        $update->execute(); 

    } else {
        header('Location: index.php');
        die();
    }
}

Instead of using $username in my query, I choose $userId and it works. 我选择使用$ userId而不是在查询中使用$ username,它可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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