【问题标题】:how to insert if value not exists in knex (nodejs)如果knex(nodejs)中不存在值,如何插入
【发布时间】:2018-01-09 13:12:47
【问题描述】:

我对 knex(和节点 js)非常陌生。如果存在,我需要编写插入,但我无法做到这一点。

下面不工作,但有没有办法做到这一点?

var val = "water";
knex('ingredients').insert({'name': val})
      .select(val)
      .whereNotExists(knex('ingredients').where('name', val))
  )

【问题讨论】:

    标签: knex.js


    【解决方案1】:

    当我尝试这样做时,.select.whereNotExists.insert 函数之后被 KNEX 忽略。所以这里有另外 2 种方法可以到达那里......

    1. 通过 KNEX 嵌入 SQL。
    2. 使用 KNEX 首先尝试检索匹配项,然后执行插入操作
      与否,取决于结果。
    3. 我从您的问题中假设的另一种方法不是您想要的方向,但我通常使用的方法是创建一个数据库约束,它将 拒绝重复。

    在 KNEX 中嵌入 SQL:

    您想要的 SQL 如下所示:

    INSERT INTO ingredients (name)
        SELECT "name_val"
        WHERE NOT EXISTS 
             (SELECT 1 FROM ingredients WHERE name = "name_val");
    

    所以将它放入 KNEX 看起来像:

    var val = "water";
    var rawStr = "INSERT INTO ingredients (name) SELECT ? WHERE NOT EXISTS(SELECT 1 FROM ingredients WHERE name = ?)";
    return knex.raw(rawStr, [val, val])
        .on('query', function(data) {
            console.log("ON-QUERY data:", data);
        });
    

    可选的.on('query' 是一个非常方便的故障排除工具,用于查看您是否获得了预期的 SQL。 (另请参阅:knexjs.org 站点中的 query-error 和 query-results)此方法的缺点是副本会静默失败,因此不会通知任何人失败。

    原生 KNEX:

    var val = "water";
    return knex('ingredients')
      .select()
      .where('name', val)
      .then(function(rows) {
        if (rows.length===0) {
          // no matching records found
          return knex('ingredients').insert({'name': val})
        } else {
          // return or throw - duplicate name found
        }
      })
      .catch(function(ex) {
        // you can find errors here.
      })
    

    使用第二种方法,我怀疑您可能更容易受到并发问题的影响,如果您的应用程序使用量很大,两个用户都尝试进行“同时”更新,但结果出乎意料。从好的方面来说,这种方法可以很容易地捕获并响应您的用户存在重复名称错误。

    【讨论】:

    • 我尝试了 rawStr 变体,它经常让我发现死锁。不知道为什么。
    • 无赖。为了解决这个问题,我首先尝试使用.on('query' 显示的 SQL,然后通过 SQL 命令窗口运行它,看看是否会出现同样的问题。最后,死锁是数据库处理问题,所以这个问题的根源是您正在使用的某些SQL序列相互冲突。因此,您需要确定哪些 SQL(和/或 DB 提交控制设置)导致了冲突。 Knex 的目的只是为您将代码翻译成 SQL。
    • 当我为一个查询(一次)运行代码时,一切正常。就像在mysql中直接运行所有sql一样。但是,当使用 knex 与许多产品一起运行时(可能是因为异步的事情)。 SQL 是正确的: INSERT INTO product_ingredients (ingredient_id, product_id) SELECT 450, 28 WHERE NOT EXISTS(SELECT 1 FROM product_ingredients WHERE ingredients_id = 450 and product_id = 28);不确定,为什么这里会发生死锁。
    • 顺便说一句,如果我选择第二个查询,那么我不会收到任何错误(但是,虽然我没有在整个数据上运行)。
    • 不幸的是,原始 SQL 的正确性(或者可能不是 - 由于死锁问题)超出了我的专业知识。我确实在这里看到了围绕您的目标的 MySQL 讨论:stackoverflow.com/questions/17991479/… ... 它建议使用不同的 SQL 来实现您的目标。
    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 2015-05-09
    • 2012-06-07
    • 2012-05-21
    • 2011-01-14
    • 2018-09-17
    • 2012-10-12
    • 1970-01-01
    相关资源
    最近更新 更多