Knex.js 从选择插入

Tur*_*yes 5 javascript node.js knex.js

我正在尝试通过 Knex.js 生成如下查询:

INSERT INTO table` ("column1", "column2")
SELECT "someVal", 12345)
WHERE NOT EXISTS (
    SELECT 1
    FROM table
    WHERE "column2" = 12345
)
Run Code Online (Sandbox Code Playgroud)

基本上,我只想在特定值不存在时插入值。但是 Knex.js 似乎不知道如何做到这一点;如果我调用knex.insert()(没有值),它会生成一个“插入默认值”查询。

我尝试了以下方法:

pg.insert()
                .into(tableName)
                .select(_.values(data))
                .whereNotExists(
                    pg.select(1)
                        .from(tableName)
                        .where(blah)
                );
Run Code Online (Sandbox Code Playgroud)

但这仍然只是给了我默认值的东西。我尝试添加一个.columns(Object.keys(data))希望insert()能够兑现这一点,但没有运气。

是否可以使用 knex 生成我想要的查询,或者我只需要构建一个原始查询,而无需 Knex.js 方法?

max*_*kov 7

我找到的最全面的答案(带有 的明确列名称INSERT,以及 - 语句中的自定义值SELECT)如下:

https://github.com/knex/knex/issues/1056#issuecomment-156535234

克里斯·布鲁姆

这是该解决方案的修改副本:

const query = knex
  // this part generates INSERT-clause of the
  // query (with column-names): INSERT "tablename" ("field1", "field2" ..)
  .into(knex.raw('?? (??, ??)', ['tableOrders', 'field_user_id', 'email_field']))

  // and this part generates the "SELECT"-clause (even though it starts with `.insert`)
  .insert(function() {
    this
      .select(
        'user_id',  // select from column without alias
        knex.raw('? AS ??', ['jdoe@gmail.com', 'email']),  // select static value with alias
      )
      .from('users AS u')
      .where('u.username', 'jdoe')
   });
console.log(query.toString());
Run Code Online (Sandbox Code Playgroud)

和 SQL 输出:

insert into "orders" ("user_id", "email")
  select "user_id", 'jdoe@gmail.com' AS "email"
  from "users" as "u"
  where "u"."username" = 'jdoe'
Run Code Online (Sandbox Code Playgroud)

使用这种方法,例如可以从预定义的“模板”表( )填充“配置文件”表(select from template),并同时将模板数据与用户偏好/其他值(如NOW())合并。


另一种方法(由 Knex 开发人员提供):https://github.com/knex/knex/commit/e74f43cfe57ab27b02250948f8706d16c5d821b8#diff-cb48f4af7c014ca6a7a2008c9d280573R608 - 也可以knex.raw


小智 5

我相信选择需要传递到插入中:

pg.insert(knex.select().from("tableNameToSelectDataFrom")).into("tableToInsertInto");
Run Code Online (Sandbox Code Playgroud)

另外,为了选择常量值或表达式,您需要在选择中使用 knex.raw 表达式:

knex.select(knex.raw("'someVal',12345")).from("tableName")
Run Code Online (Sandbox Code Playgroud)

这是我的第一篇文章,我没有测试您的具体示例,但我已经使用上述技术完成了类似的事情,就像您所要求的那样。