[development] correct way to update/insert a value in a table
Larry Garfield
larry at garfieldtech.com
Mon Mar 31 18:58:35 UTC 2008
In Drupal 5/6, we use update-or-insert. That's because we're able to set the MySQL and Postgres drivers to return the number of rows *matched*, rather than the number of rows *changed*. That does mean that, technically, db_affected_rows() is misnamed, but it maps to the underlying function name in PHP (which can toggle modes).
This has come up recently in the Drupal 7 database API development, because PDO does not let you return the number of rows matched, only the number changed. That means the update-or-insert logic breaks if we try to set a record to the value it already has (which is not uncommon). What we really need here is a merge query, but the syntax for that is wildly different on every database. At the moment we are planning to introduce a new "merge" query builder that will replace the update-or-insert pattern with a single, database-optimized query (such as INSERT ... ON DUPLICATE KEY UPDATE ... on MySQL). See the issue for more details: http://drupal.org/node/225450
So for now, yes, the logic shown below is what you should use.
--Larry Garfield
On Mon, 31 Mar 2008 11:34:07 -0700, "mark burdett" <mfburdett at gmail.com> wrote:
> I happened to notice last night that db_affected_rows() is the number of
> matched rows in the WHERE clause, not the number of rows that were
> actually
> changed. So (maybe only in drupal) if the data is the same these count as
> "affected" rows.
>
> If you grep core for db_affected_rows you see that the logic is
> db_query("UPDATE {variable} SET value = '%s' WHERE name = '%s'",
> if (!db_affected_rows()) {
> @db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')",
> }
>
>
> --mark
>
> On Mon, Mar 31, 2008 at 9:13 AM, Earnie Boyd
> <earnie at users.sourceforge.net>
> wrote:
>
>> Quoting John Fiala <jcfiala at gmail.com>:
>>
>> > On Mon, Mar 31, 2008 at 6:43 AM, Lluís <enboig at gmail.com> wrote:
>> >> I need to save a value inside a table; I think the best/fast way of
>> >> doing so is:
>> >>
>> >
>> > Personally I like to keep track internally if a row's been saved to
>> > the db or not - but I've seen some folks try the UPDATE statement,
>> > call db_affected_rows to see if any rows were changed, and if none
>> > were, to do the insert.
>>
>> Doesn't work if data is the same; no rows will be updated and
>> db_affected_rows will return 0. The method the OP used is correct
>> insert else update.
>>
>> Earnie -- http://for-my-kids.com/
>> -- http://give-me-an-offer.com/
>>
>>
>
>
More information about the development
mailing list