如果记录不存在,则插入;如果存在,则更新

时间:2019-07-19 22:12:41

标签: javascript mysql sql node.js

我正在尝试使用Multivit4min(github)的Node.js库制作TS3机器人 该机器人应执行以下操作: (这里的表: 尼克(txt)| cldbid(int)| clid(txt)| lastChannel(int) 顺便说一句客户ID的clid应该是客户的唯一ID)

事件#1-客户端连接到服务器: -检查数据库中是否存在带有client.UID的记录:     是:将其lastChannel更新为event.channel.channelId     否:插入client.nick,cldbid,UID和event.channel.channelId

事件2-客户端移至另一个频道: -将lastChannel更新为event.channel.channelId

事件#3-客户端移至特定频道: -通过他的UID搜索记录并将他的lastChannel保存到变量

通常,我知道如何使用Node进行操作,但是我却很难使用SQL,因为它始终会显示一些错误或无法正常工作。

我尝试了许多查询,但没有一个有效。我所做的最好的事情是从堆栈上的其他线程获取的代码中的“ REPLACE”,它应该自动检查它是否存在,然后更新或不存在-然后插入。但总是会创建越来越多的记录副本。

这是我的一些代码:

ts3.on("clientconnect", event => {

        sql.query("SELECT * FROM `users` WHERE `clid`= " + event.client.getUID(), 

        function(err, result){
            if(err){
                console.log(time.get() + "Error SQL: " + err)
            }else{
                if(row && row.length){
                    sql.query("REPLACE INTO users (nick, cldbid, clid, lastChannel) VALUES ('" + event.client.nickname + "','" + event.client.getDBID() + "','" + event.client.getUID() + "','" + config.lastChannel + "');",
                    function(err,result){
                        if (err){
                            console.log(time.get()+err)
                        }else{
                            console.log(time.get() + `Dodano użytkownika ${event.client.nickname} do bazy danych`)
                        }
                    })
                }
            }
        })

})

我真的不希望您为我创建整个代码。我只是要求使用最终的“ if”进行SQL查询,因为如您所见,我的第四个想法(我之前说过我尝试了很多方法)是基于SELECT的,并且取决于结果,是对记录进行UPDATE还是INSERT。

随意询问有关var,代码等的信息,我整夜都..

2 个答案:

答案 0 :(得分:0)

我想到了如下代码:

sql.query("INSERT INTO users (nick,cldbid,clid,lastChannel) VALUES('"+event.client.nickname+"',"+event.client.getDBID()+",'"+event.client.getUID()+
        "',"+config.lastChannel+") ON DUPLICATE KEY UPDATE lastchannel="+event.channel.cid+";", 

        function(err, result){
            if(err){
                log.clog("Blad SQL #clientmoved: " + err)
            }else{
                log.clog("Pomyslnie addded/updated record of "+event.client.nickname)
            }
        })

现在我需要帮助,如何将1个参数从记录的第x列保存到变量。 (int)

答案 1 :(得分:0)

要回答原始问题,您需要ON DUPLICATE KEY UPDATE。不过,更重要的是,您的代码容易受到SQL注入的攻击。<​​/ p>

永远不要那样将值直接插入查询中。考虑示例:

db.query("INSERT INTO messages (message, username) VALUES ('" + message + "', "' + username + ')");

如果username是我的身份验证用户名,但是message是我在UI中键入的任何值,那么我可以通过发送类似I am stupid', 'someone_else') --的消息来伪装成其他人/ p>

SQL将如下所示:

INSERT INTO messages (message, username)
VALUES ('I am stupid', 'someone_else') --', 'my_username')

--', 'my_username')位被视为注释,因此看起来someone_elseI am stupid。这是Web应用程序中最常见且最容易利用的漏洞之一。

解决方案1 ​​

您可以参数化您的查询:

db.query(`
  INSERT INTO messages (message, username)
  VALUES (?, ?)
`, [message, username]);

这是安全的,但(我认为)较难阅读,因此必须始终保持一致。

以您的示例为例,

sql.query("INSERT INTO users (nick,cldbid,clid,lastChannel) VALUES(?,?,?,?) ON DUPLICATE KEY UPDATE lastchannel=?;", 
  [event.client.nickname, event.client.getDBID(), event.client.getUID(), config.lastChannel, event.channel.cid],
        function(err, result){
            if(err){
                log.clog("Blad SQL #clientmoved: " + err)
            }else{
                log.clog("Pomyslnie addded/updated record of "+event.client.nickname)
            }
        })

解决方案2

https://www.atdatabases.org提供了相对易于使用的数据库API,并且完全免受此类攻击。您只需这样做:

import connect, {sql} from '@databases/pg';

const db = connect();

db.query(sql`
  INSERT INTO messages (message, username)
  VALUES (${message}, ${username})
`);

安全地执行相同的查询。 sql标记可确保正确处理/转义数据,并且@databases/pg自动强制您始终添加sql标记。 N.B.则参数周围没有引号。

在您的示例中,类似

db.query(sql`INSERT INTO users (nick,cldbid,clid,lastChannel) VALUES(${event.client.nickname},${event.client.getDBID()},${event.client.getUID()},${config.lastChannel}) ON DUPLICATE KEY UPDATE lastchannel=${event.channel.cid};`).then(
  result => log.clog("Pomyslnie addded/updated record of "+event.client.nickname),
  err => log.clog("Blad SQL #clientmoved: " + err),
);