values(id='some_id', data='some data to insert')
on_conflict_stmt = insert_stmt.on_duplicate_key_update(
- data=stmt.values.data,
+ data=stmt.inserted.data,
status='U'
)
--- /dev/null
+.. change::
+ :tags: bug, mysql
+ :tickets: 4072
+
+ Changed the name of the ``.values`` attribute of the new MySQL
+ INSERT..ON DUPLICATE KEY UPDATE construct to ``.inserted``, as
+ :class:`.Insert` already has a method called :meth:`.Insert.values`.
+ The ``.inserted`` attribute ultimately renders the MySQL ``VALUES()``
+ function.
\ No newline at end of file
MySQL allows "upserts" (update or insert)
of rows into a table via the ``ON DUPLICATE KEY UPDATE`` clause of the
``INSERT`` statement. A candidate row will only be inserted if that row does
-not match an existing primary or unique key in the table; otherwise, an UPDATE will
-be performed. The statement allows for separate specification of the
+not match an existing primary or unique key in the table; otherwise, an UPDATE
+will be performed. The statement allows for separate specification of the
values to INSERT versus the values for UPDATE.
SQLAlchemy provides ``ON DUPLICATE KEY UPDATE`` support via the MySQL-specific
data='inserted value')
on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update(
- data=insert_stmt.values.data,
+ data=insert_stmt.inserted.data,
status='U'
)
unless they are manually specified explicitly in the parameters.
In order to refer to the proposed insertion row, the special alias
-:attr:`~.mysql.dml.Insert.values` is available as an attribute on
+:attr:`~.mysql.dml.Insert.inserted` is available as an attribute on
the :class:`.mysql.dml.Insert` object; this object is a
:class:`.ColumnCollection` which contains all columns of the target
table::
author='jlh')
do_update_stmt = stmt.on_duplicate_key_update(
data="updated value",
- author=stmt.values.author
+ author=stmt.inserted.author
)
conn.execute(do_update_stmt)
-When rendered, the "values" namespace will produce the expression
+When rendered, the "inserted" namespace will produce the expression
``VALUES(<columnname>)``.
.. versionadded:: 1.2 Added support for MySQL ON DUPLICATE KEY UPDATE clause
val.type = column.type
value_text = self.process(val.self_group(), use_schema=False)
elif isinstance(val, elements.ColumnClause) \
- and val.table is on_duplicate.values_alias:
+ and val.table is on_duplicate.inserted_alias:
value_text = 'VALUES(' + self.preparer.quote(column.name) + ')'
else:
value_text = self.process(val.self_group(), use_schema=False)
"""
@property
- def values(self):
- """Provide the ``values`` namespace for an ON DUPLICATE KEY UPDATE statement
+ def inserted(self):
+ """Provide the "inserted" namespace for an ON DUPLICATE KEY UPDATE statement
MySQL's ON DUPLICATE KEY UPDATE clause allows reference to the row
that would be inserted, via a special function called ``VALUES()``.
This attribute provides all columns in this row to be referenaceable
such that they will render within a ``VALUES()`` function inside the
- ON DUPLICATE KEY UPDATE clause.
+ ON DUPLICATE KEY UPDATE clause. The attribute is named ``.inserted``
+ so as not to conflict with the existing :meth:`.Insert.values` method.
.. seealso::
:ref:`mysql_insert_on_duplicate_key_update` - example of how
- to use :attr:`.Insert.values`
+ to use :attr:`.Insert.inserted`
"""
- return self.values_alias.columns
+ return self.inserted_alias.columns
@util.memoized_property
- def values_alias(self):
- return alias(self.table, name='values')
+ def inserted_alias(self):
+ return alias(self.table, name='inserted')
@_generative
def on_duplicate_key_update(self, **kw):
:ref:`mysql_insert_on_duplicate_key_update`
"""
- values_alias = getattr(self, 'values_alias', None)
- self._post_values_clause = OnDuplicateClause(values_alias, kw)
+ inserted_alias = getattr(self, 'inserted_alias', None)
+ self._post_values_clause = OnDuplicateClause(inserted_alias, kw)
return self
class OnDuplicateClause(ClauseElement):
__visit_name__ = 'on_duplicate_key_update'
- def __init__(self, values_alias, update):
- self.values_alias = values_alias
+ def __init__(self, inserted_alias, update):
+ self.inserted_alias = inserted_alias
if not update or not isinstance(update, dict):
raise ValueError('update parameter must be a non-empty dictionary')
self.update = update
)
def test_from_values(self):
- stmt = insert(
- self.table, [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}])
+ stmt = insert(self.table).values(
+ [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}])
stmt = stmt.on_duplicate_key_update(
- bar=stmt.values.bar, baz=stmt.values.baz)
+ bar=stmt.inserted.bar, baz=stmt.inserted.baz)
expected_sql = (
'INSERT INTO foos (id, bar) VALUES (%s, %s), (%s, %s) '
'ON DUPLICATE KEY UPDATE bar = VALUES(bar), baz = VALUES(baz)'
self.assert_compile(stmt, expected_sql)
def test_from_literal(self):
- stmt = insert(
- self.table, [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}])
+ stmt = insert(self.table).values(
+ [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}])
stmt = stmt.on_duplicate_key_update(bar=literal_column('bb'))
expected_sql = (
'INSERT INTO foos (id, bar) VALUES (%s, %s), (%s, %s) '
self.assert_compile(stmt, expected_sql)
def test_python_values(self):
- stmt = insert(
- self.table, [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}])
+ stmt = insert(self.table).values(
+ [{'id': 1, 'bar': 'ab'}, {'id': 2, 'bar': 'b'}])
stmt = stmt.on_duplicate_key_update(bar="foobar")
expected_sql = (
'INSERT INTO foos (id, bar) VALUES (%s, %s), (%s, %s) '
foos = self.tables.foos
with testing.db.connect() as conn:
conn.execute(insert(foos, dict(id=1, bar='b', baz='bz')))
- stmt = insert(foos, [dict(id=1, bar='ab'), dict(id=2, bar='b')])
- stmt = stmt.on_duplicate_key_update(bar=stmt.values.bar)
+ stmt = insert(foos).values(
+ [dict(id=1, bar='ab'), dict(id=2, bar='b')])
+ stmt = stmt.on_duplicate_key_update(bar=stmt.inserted.bar)
result = conn.execute(stmt)
eq_(result.inserted_primary_key, [2])
eq_(
def test_last_inserted_id(self):
foos = self.tables.foos
with testing.db.connect() as conn:
- stmt = insert(foos, {"bar": "b", "baz": "bz"})
+ stmt = insert(foos).values({"bar": "b", "baz": "bz"})
result = conn.execute(
stmt.on_duplicate_key_update(
- bar=stmt.values.bar, baz="newbz")
+ bar=stmt.inserted.bar, baz="newbz")
)
eq_(result.inserted_primary_key, [1])
- stmt = insert(foos, {"id": 1, "bar": "b", "baz": "bz"})
+ stmt = insert(foos).values({"id": 1, "bar": "b", "baz": "bz"})
result = conn.execute(
stmt.on_duplicate_key_update(
- bar=stmt.values.bar, baz="newbz")
+ bar=stmt.inserted.bar, baz="newbz")
)
eq_(result.inserted_primary_key, [1])