On 01/18/2016 07:41 PM, gbr wrote:
> Sorry, I'm having difficulties following your explanation. Would you
> mind extending on it a bit?
>
> that error should only occur if the list of elements you're passing to
> insert.values() contains inconsistent keys. As long as each dictionary
> has the same keys, that error won't occur.
>
>
> With "keys", do you mean the primary key column in your example (the
> 'id' column)? Or column 'foo'?
>
> The old behavior was a bug, we just kept it at 1.1 in case people
> were relying upon the buggy
> behavior of it forcing NULL for columns where a default generator
> should
> have been used.
>
>
> So, if I upgrade to 1.1 the old behaviour will be restored? Are there
> any plans of making it a feature and maintaining it?
>
>
> values = [
> {'id': 1, 'data': 'data1', 'foo': 'plainfoo'},
> {'id': 2, 'data': 'data2'},
> {'id': 3, 'data': 'data3', 'foo': 'otherfoo'},
> ]
>
>
> Which one of those dicts causes the issue and why? Is it the fact that
> 'foo' is being set client-side, that the id=2 row has no value, that the
> id=1 and id=3 rows have different values? What's the "proper" way of
> resolving this without relying on buggy (and potentially not maintained)
> behaviour?
in SQL, an INSERT statement looks like this:
INSERT INTO table (col1, col2, col3) VALUES ('x', 'y', 'z')
Above, note that the INSERT statement has one section that names out the
target columns individually; the second part is the VALUES clause that
names out the values.
With the error message you are getting, even though I've yet to see a
code example here, it indicates the kind of SQL you're going for is this:
INSERT INTO table (col1, col2, col3) VALUES
('x', 'y', 'z'), ('q', 'p', 'r'), ('a', 'b', 'c')
that is, there are *multiple* groups of values, each indicating an
individual row. If you weren't using this form of statement then you
wouldn't be getting that error message.
Above, it should be apparent that each set of "values" has to correspond
with the original list of column names that serve as the targets; in
this case "col1, col2, col3".
the SQL would not be valid if we said:
INSERT INTO table (col1, col2, col3) VALUES
('x', 'y', 'z'), ('q', 'r'), ('a', 'b', 'c')
can you see why? The second tuple doesn't have enough values.
Looking at the code example, we see:
values = [
{'id': 1, 'data': 'data1', 'foo': 'plainfoo'},
{'id': 2, 'data': 'data2'},
{'id': 3, 'data': 'data3', 'foo': 'otherfoo'},
]
Even though we have three independent dictionaries, when you pass a list
of these to the SQLAlchemy insert().values() method, it means you want
it to render the VALUES all at once as above. So to render SQL of this
form, each dictionary needs to have the *identical* set of keys, in this
case those keys being 'id', 'data', and 'foo'.
The solution then is to ensure all dictionaries have the same keys:
values = [
{'id': 1, 'data': 'data1', 'foo': 'plainfoo'},
{'id': 2, 'data': 'data2', 'foo': None},
{'id': 3, 'data': 'data3', 'foo': 'otherfoo'},
]
SQLAlchemy also supports a so-called "executemany" form, where you
instead pass a list of dictionaries to connection.execute(). This is
the more common form. However, as it needs to apply each dictionary to
the statement as fixed SQL, it requires the same condition on the
incoming data.
> The old behavior was a bug, we just kept it at 1.1 in case people
> were relying upon the buggy
> behavior of it forcing NULL for columns where a default generator
> should
> have been used.
>
>
> So, if I upgrade to 1.1 the old behaviour will be restored? Are there
> any plans of making it a feature and maintaining it?
OK let me restate that sentence, as it is unclear and I also made a
typo: "The old behavior, that of the 0.9 series and earlier, is a bug.
It is never correct and will not be restored. The reason the bug was
not fixed in 0.9, and instead was added as a behavioral change in 1.0
(not 1.1), was because it is possible that application were relying upon
the old and broken behavior in order to function as expected.
Applications which upgrade to 1.0 must correct their reliance on the 0.9
and earlier behavior in order to function correctly, by ensuring that
each dictionary passed to insert().values() in a list contains the
identical collection of string dictionary key values".
Does that help?
>
> Thanks for your help.
>
> On Monday, 18 January 2016 18:23:04 UTC+11, gbr wrote:
>
> |I've upgraded from a SQLA version 0.9.x to 1.0.9. Previously, I did
> the following when inserting new records:
>
> - Column('flag', Boolean, server_default=sql.expression.false()) |||I didn't set those columns locally and didn't include them in the
> insert statement when I wanted them to be False
> |- Column('date', Date, nullable=False) I didn't set those columns
> as part of the insert when I wanted `date=None`
> - Column('number', Float, nullable=True) I assigned integer values
> to the column which were implicitly "casted" to floats
>
> This behaviour changed which is described here
> (
http://docs.sqlalchemy.org/en/latest/changelog/migration_10.html#python-side-defaults-invoked-for-each-row-invidually-when-using-a-multivalued-insert
> <
http://docs.sqlalchemy.org/en/latest/changelog/migration_10.html#python-side-defaults-invoked-for-each-row-invidually-when-using-a-multivalued-insert>)