Javascript 如果记录不存在则插入,如果存在则更新
我正在尝试从Multivit4min github使用Node.js库制作一个TS3机器人 bot应该这样做: 这是桌子: nick txt | cldbid int | clidtxt | lastChannel int 顺便说一句,clid是客户端id,应该是客户端的唯一id 事件1-客户端连接到服务器: -检查数据库中是否存在client.UID记录: 是:将其最后一个频道更新为event.channel.channelId 否:插入client.nick、cldbid、UID和event.channel.channelId 事件2-客户端移动到另一个通道: -将lastChannel更新为event.channel.channelId 事件3-客户端移动到特定通道: -按他的UID搜索记录,并将其最后一个频道保存到变量中 一般来说,我知道如何使用Node进行部分操作,但我很难使用SQL,因为它总是显示一些错误或不能正常工作 我试过很多问题,但都不管用。我所做的最好的事情就是从堆栈上的其他线程中得到一些代码,这些代码是“替换”的,它应该自动检查它是否存在,然后更新,或者如果不存在,然后插入。但它总是在创造越来越多的记录副本 以下是我的一些代码:Javascript 如果记录不存在则插入,如果存在则更新,javascript,mysql,sql,node.js,Javascript,Mysql,Sql,Node.js,我正在尝试从Multivit4min github使用Node.js库制作一个TS3机器人 bot应该这样做: 这是桌子: nick txt | cldbid int | clidtxt | lastChannel int 顺便说一句,clid是客户端id,应该是客户端的唯一id 事件1-客户端连接到服务器: -检查数据库中是否存在client.UID记录: 是:将其最后一个频道更新为event.channel.channelId 否:插入client.nick、cldbid、UID和event
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`)
}
})
}
}
})
})
我真的不希望你为我创建完整的代码。我只是要求SQL查询具有最终的ifs,因为正如您所看到的,我之前说过的第四个想法,我尝试了许多方法,基于SELECT并根据结果更新或插入记录
请随意询问变量、代码等,我花了整整一个晚上。我想出了如下代码:
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)
}
})
现在我需要帮助如何将一个参数从记录的x列保存到变量。int要回答原始问题,您需要重复密钥更新。但更重要的是,您的代码容易受到SQL注入的攻击 您不应该像这样直接将值插入查询中。考虑这个例子:
db.query("INSERT INTO messages (message, username) VALUES ('" + message + "', "' + username + ')");
如果用户名是我经过身份验证的用户名,但消息是我在UI中键入的任何值,我可以通过发送类似“我很笨”、“其他人”的消息来假装是其他人-
SQL将如下所示:
INSERT INTO messages (message, username)
VALUES ('I am stupid', 'someone_else') --', 'my_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)
}
})
-','my_username'位被视为一条评论,因此看起来好像有人说我很愚蠢。这是web应用程序中最常见且易于利用的漏洞之一
解决方案1
您可以将查询参数化:
db.query(`
INSERT INTO messages (message, username)
VALUES (?, ?)
`, [message, username]);
这是安全的,但在我看来更难理解,你必须非常小心,始终坚持这样做
对于您的示例,这看起来像:
INSERT INTO messages (message, username)
VALUES ('I am stupid', 'someone_else') --', 'my_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
提供相对易于使用且完全安全的数据库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标记。注意:参数周围没有引号
你的例子是这样的
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),
);
重复密钥更新是您需要的。此外,请看准备好的声明。您在这里留下了一个巨大的sql注入漏洞。实际上它几乎不可能复制,因为teamspeak上的最大昵称并不长。大多数用户甚至不知道SQL注入。只有1%的用户可以使用它,但我不认为他们会尝试使用昵称来删除数据库,这在我的代码中不是关键错误,甚至不是小错误,因为我将使用try{}catch{}来防止SQL出错。删除数据库到目前为止不是SQL注入可以做的最糟糕的事情,实际上这是一个比较温和的结果。窃取敏感用户数据和在服务器上执行任意代码是的,这也是您应该担心的。至于REPLACE-INTO,它需要在您监视的列上有一个唯一的键。那里的数据是公共的,ts服务器上的每个人都可以检查它,而且即使有人会设法使用node.js执行一些不会对我的机器造成真正伤害的代码,我唯一保存在那里的就是这个bot@Timekiller该规则是否也适用于键上重复?