Use multiple conflict_target in ON CONFLICT clause

前端 未结 9 794
傲寒
傲寒 2020-11-29 02:25

I have two columns in table col1, col2, they both are unique indexed (col1 is unique and so is col2).

I need at insert into this table, u

9条回答
  •  北海茫月
    2020-11-29 02:47

    You can typically (I would think) generate a statement with only one on conflict that specifies the one and only constraint that is of relevance, for the thing you are inserting.

    Because typically, only one constraint is the "relevant" one, at a time. (If many, then I'm wondering if something is weird / oddly-designed, hmm.)

    Example:
    (License: Not CC0, only CC-By)

    // there're these unique constraints:
    //   unique (site_id, people_id, page_id)
    //   unique (site_id, people_id, pages_in_whole_site)
    //   unique (site_id, people_id, pages_in_category_id)
    // and only *one* of page-id, category-id, whole-site-true/false
    // can be specified. So only one constraint is "active", at a time.
    
    val thingColumnName = thingColumnName(notfificationPreference)
    
    val insertStatement = s"""
      insert into page_notf_prefs (
        site_id,
        people_id,
        notf_level,
        page_id,
        pages_in_whole_site,
        pages_in_category_id)
      values (?, ?, ?, ?, ?, ?)
      -- There can be only one on-conflict clause.
      on conflict (site_id, people_id, $thingColumnName)   <—— look
      do update set
        notf_level = excluded.notf_level
      """
    
    val values = List(
      siteId.asAnyRef,
      notfPref.peopleId.asAnyRef,
      notfPref.notfLevel.toInt.asAnyRef,
      // Only one of these is non-null:
      notfPref.pageId.orNullVarchar,
      if (notfPref.wholeSite) true.asAnyRef else NullBoolean,
      notfPref.pagesInCategoryId.orNullInt)
    
    runUpdateSingleRow(insertStatement, values)
    

    And:

    private def thingColumnName(notfPref: PageNotfPref): String =
      if (notfPref.pageId.isDefined)
        "page_id"
      else if (notfPref.pagesInCategoryId.isDefined)
        "pages_in_category_id"
      else if (notfPref.wholeSite)
        "pages_in_whole_site"
      else
        die("TyE2ABK057")
    

    The on conflict clause is dynamically generated, depending on what I'm trying to do. If I'm inserting a notification preference, for a page — then there can be a unique conflict, on the site_id, people_id, page_id constraint. And if I'm configuring notification prefs, for a category — then instead I know that the constraint that can get violated, is site_id, people_id, category_id.

    So I can, and fairly likely you too, in your case?, generate the correct on conflict (... columns ), because I know what I want to do, and then I know which single one of the many unique constraints, is the one that can get violated.

提交回复
热议问题