【问题标题】:Deleting records on a database删除数据库中的记录
【发布时间】:2019-06-03 08:38:41
【问题描述】:

我有一个完美运行的日志记录命令,唯一的问题是我无法完成命令的off 部分。如果 guildid 匹配,我需要它来删除两条记录 (guildid, channel)。 这是我尝试过的。

if (args[0] === 'off') {
    message.channel.send('Logging turned off!');
    const del = db.prepare('DELETE FROM logging WHERE guildid = ?;');
    del.run({
        guildid: `${message.guild.id}`
    });
    return;

看照片,当运行args off时,如果公会内容与公会匹配,我需要它删除公会内容(495602...)和频道内容(

【问题讨论】:

    标签: node.js discord.js better-sqlite3


    【解决方案1】:

    您当前的答案是使用准备好的语句的错误方法。如果你使用你的姿势,你就会向 SQL 注入敞开心扉,因为你没有将要在语句中使用的值解释为值,而是将其用作整个语句的一部分,然后运行不带参数的语句.这意味着我可能会提供一个可能不会完全按照您的想法执行的值。

    例如以下不会做任何事情,

    const $rowid = "3 OR rowid = 4";
    const deleteStatement = db.prepare("DELETE FROM lorem WHERE rowid = $rowid");
    deleteStatement.run({$rowid});
    deleteStatement.finalize();
    

    但这会删除 rowid 为 3 或 4 的元素:

    const $rowid = "3 OR rowid = 4";
    const deleteStatement = db.prepare(`DELETE FROM lorem WHERE rowid = ${$rowid}`);
    deleteStatement.run();
    deleteStatement.finalize();
    

    相反,请查看sqlite3 documentation here

    您需要将准备好的语句实际参数化,如下所示:

    const sqlite3 = require("sqlite3").verbose();
    const db = new sqlite3.Database(":memory:");
    
    db.serialize(function() {
        // Make the table
        db.run("CREATE TABLE lorem (info TEXT)");
    
        // Create some dummy data
        const insertStatement = db.prepare("INSERT INTO lorem VALUES (?)");
        for (let i = 0; i < 5; i++) {
            insertStatement.run(`My Data ${i}`);
        }
        insertStatement.finalize();
    
        // Delete some data
        const deleteStatement = db.prepare("DELETE FROM lorem WHERE rowid = $rowid");
        deleteStatement.run({
            $rowid: 3
        });
        deleteStatement.finalize();
    
        // Print elements
        db.each("SELECT rowid AS id, info FROM lorem", (err, {id, info}) => console.log(`${id}: ${info}`));
    });
    
    db.close();
    

    【讨论】:

    • 我想我会复制它并看看它是如何工作的,但我应该正确指定,我正在使用 better-sqlite3 并且您的代码似乎不适用于它。我收到 verbose is not a functionsqlite3.Database is not a constructordb.serialize is not a function 之类的错误
    • @RagnarLothbrok 好的,我使用了sqlite3,但Statement#run() API 看起来非常相似。主要的是您需要让run() 处理参数,而不是用您可能未清理或无法控制的模板文字来替换它们。这就是潜在注入的用武之地。
    【解决方案2】:

    对于将来寻找如何做到这一点的任何人来说,这就是答案。 编辑:直到 2 天才能标记为答案哈哈

    if (args[0] === 'off') {
    message.channel.send('Logging turned off!');
    db.prepare(`DELETE FROM logging WHERE guildid = '${message.guild.id}'`).run();
    return;
    

    【讨论】:

    • 不要以这种方式使用准备好的语句。你对潜在的滥用敞开心扉。看我的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-04
    • 1970-01-01
    • 2013-12-06
    • 2014-01-13
    相关资源
    最近更新 更多