【问题标题】:Knex.js insert from selectKnex.js 从选择中插入
【发布时间】:2015-04-25 21:02:41
【问题描述】:

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

    INSERT INTO table ("column1", "column2")
    SELECT "someVal", 12345
    WHERE NOT EXISTS (
        SELECT 1
        FROM table
        WHERE "column2" = 12345
    )

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

我尝试了以下方法:

    pg.insert()
        .into(tableName)
        .select(_.values(data))
        .whereNotExists(
            pg.select(1)
                .from(tableName)
                .where(blah)
        );

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

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

【问题讨论】:

    标签: javascript node.js knex.js


    【解决方案1】:

    我认为选择需要传递到插入中:

    pg.insert(knex.select().from("tableNameToSelectDataFrom")).into("tableToInsertInto");
    

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

    knex.select(knex.raw("'someVal',12345")).from("tableName")
    

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

    【讨论】:

    • 有时我在目标表(或自动生成的字段)中有很好的默认值,所以我需要列出要插入的列名。在您的示例中,此块 pg.insert( ...) 假定提供的 knex.select 将返回所有列的值,并且以正确的顺序(数据库模式中表中列的顺序) - 有时它只是不起作用跨度>
    【解决方案2】:

    我找到的最全面的答案(INSERT 的明确列名和SELECT-statement 中的自定义值)在这里:

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

    Chris Broome

    这是该解决方案的副本:

    const query = knex
      // this part generates this part of the
      // query: INSERT "tablename" ("field1", "field2" ..)
      .into(knex.raw('?? (??, ??)', ['tableOrders', 'field_user_id', 'email_field']))
    
      // and here is the second part of the SQL with "SELECT"
      .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());
    

    和 SQL 输出:

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

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

    【讨论】:

      【解决方案3】:

      我已经设法让它在我的项目中运行,它看起来并没有那么糟糕!

      
              .knex
                  .into(knex.raw('USER_ROLES (ORG_ID, USER_ID, ROLE_ID, ROLE_SOURCE, ROLE_COMPETENCE_ID)'))
                  .insert(builder => {
                      builder
                          .select([
                              1,
                              'CU.USER_ID',
                              'CR.ROLE_ID',
                              knex.raw(`'${ROLES.SOURCE_COMPETENCE}'`),
                              competenceId,
                          ])
                          .from('COMPETENCE_USERS as CU')
                          .innerJoin('COMPETENCE_ROLES as CR', 'CU.COMPETENCE_ID', 'CR.COMPETENCE_ID')
                          .where('CU.COMPETENCE_ID', competenceId)
                          .where('CR.COMPETENCE_ID', competenceId);
      

      请注意,目前这似乎不适用于 MSSQL 上的 returning 子句(它只是被 Knex 忽略)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-25
        • 2018-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-26
        • 2020-10-19
        相关资源
        最近更新 更多