How to make an upsert query with two keys? I have a custom table with a primary key made from two fields (route, uid) and I want to use the upsert() method to insert or edit a record. The problem is that the key() method only accept one key which will be used to identify the existing row. But I have two (route and uid)


  Sets the unique / primary key field to be used as condition for this
  query.


public function key($field) {
  $this-&gt;key = $field;

  return $this;
}


Maybe I'm missing something or I misunderstand the upsert() method. So, Can I make an upsert query with two keys?

Edit: I'm using mysql.
At this moment I don't know why but if I use only one key the query works as expected (using the two database keys as a key in the upsert, when I only says $query-&gt;key('route');):

$route = \Drupal::routeMatch()-&gt;getRouteName();
$uid = $this-&gt;currentUser-&gt;id();

$query = $this-&gt;connection-&gt;upsert('forcontu_database_counter')
          -&gt;fields([
    'route' =&gt; $route,
    'uid' =&gt; $uid,
    'user_count' =&gt; 1,
    'lastcount' =&gt; time(),
  ]);
$query-&gt;key('route');
$query-&gt;execute();


If I change the uid (using a diferent user in the site) in the same route (page) Drupal insert a new record (don't make an update in the existing route) and I only use one key, in this case route.

EDIT: 

This always will work because if you see the code inside the __toString() function the key property is never used:

public function __toString() {
    // Create a sanitized comment string to prepend to the query.
    $comments = $this-&gt;connection-&gt;makeComment($this-&gt;comments);

    // Default fields are always placed first for consistency.
    $insert_fields = array_merge($this-&gt;defaultFields, $this-&gt;insertFields);

    $query = $comments . 'INSERT INTO {' . $this-&gt;table . '} (' . implode(', ', $insert_fields) . ') VALUES ';

    $values = $this-&gt;getInsertPlaceholderFragment($this-&gt;insertValues, $this-&gt;defaultFields);
    $query .= implode(', ', $values);

    // Updating the unique / primary key is not necessary.
    unset($insert_fields[$this-&gt;key]);

    $update = [];
    foreach ($insert_fields as $field) {
      $update[] = "$field = VALUES($field)";
    }

    $query .= ' ON DUPLICATE KEY UPDATE ' . implode(', ', $update);

    return $query;
  }

}


But always you need to set the key, if you don't set the key property you will get an exception:

protected function preExecute() {
  // Confirm that the user set the unique/primary key of the table.
  if (!$this-&gt;key) {
    throw new NoUniqueFieldException('There is no unique field specified.');
  }
...


Read more about this at: Why we need the key property in the Upsert class if it is never used?