sequelize: Can't update primary key

I’m having the same issue referenced in this stack overflow: http://stackoverflow.com/questions/33881189/sequelize-update-record-primary-key-value

Issue has been traced down to: https://github.com/sequelize/sequelize/blob/f482790b85ef2336bb97893c0eaa127d9d6bbc77/lib/instance.js#L334-L336

I’d be happy to provide a PR for this, but I’d like to understand the reasoning for the check first. Please advise.

What you are doing?

Trying to change a primary key value

// model definition
var User = sequelize.define('users', {
  id: {
    type: DataTypes.STRING,
    unique: true,
    primaryKey: true,
    field: 'id'
  }
)};

// usage
User.findById(oldId).then(function(user) {
 user.id = 'new value';
 user.save(); // Id remains the same in DB
});

What do you expect to happen?

user.id should save with ‘new value’

What is actually happening?

user.id reverts

Dialect: mysql __Database version: 5.7.11 __Sequelize version: sequelize@3.22.0

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Reactions: 1
  • Comments: 18 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Why does this fail silently? I literally just watched in the debugger as this.id = newId didn’t change id!

If you’re going to violate the principle of least astonishment in the name “safety”, at least throw an exception so it can be discovered.

Reopen?

As far as I understand sequelize uses th id from dataValues to generate the WHERE clause, but should use it from _previousDataValues

Just tested this again, and I discovered a problem - updating the primary key also updates the where clause (SET "id"=44 WHERE "id" = 44)

You should use bulk update instead:

return User.update({
      id: 44
    }, {
      where: {
        id: 41
      }
    })

@janmeier maybe reopen this issue? It’s really strange behavior when you are trying to set id, or part of composite primary key, then save and it does not. Maybe sequelize can write some type of warning, when trying to update PK?

This should be a bug? or an important notes in documentation? Because change primary key is a normal operation.

I agree with https://github.com/sequelize/sequelize/issues/5827#issuecomment-246118933, the PK should come from previousDataValues. What’s going to be complicated is figuring out if there are cases where that is not desirable

Hello @janmeier ,

Glad to see you have spoted a problem. But I think in my case I am not affected by this bug. Let me explain why:

The primary key that I’m trying to update is not a single PK but a composed one. What I’m trying to change is just one part of the PK, and I think sequelize only uses the first element of the PK to perform the update. So, if I try to update a model like this:

module.exports = function(sequelize, DataTypes) {
    return sequelize.define('DEVICE_MODEL', {
        DeviceModelName: {
            type: DataTypes.TEXT,
            allowNull: false,
            defaultValue: undefined,
            primaryKey: true
        },
        DeviceType: {
            type: DataTypes.TEXT,
            allowNull: false,
            defaultValue: undefined,
            primaryKey: true,
            references: {
                model: 'DEVICE_SUBTYPE',
                key: 'DeviceType'
            }
        },
        DeviceSubtype: { // change this if you gets back to the original table!
            type: DataTypes.TEXT,
            allowNull: false,
            defaultValue: undefined,
            primaryKey: true,
            references: {
                model: 'DEVICE_SUBTYPE',
                key: 'DeviceSubtypeName'
            }
        },
        DeviceManufacturer: {
            type: DataTypes.TEXT,
            allowNull: false,
            defaultValue: undefined,
            primaryKey: true,
            references: {
                model: 'DEVICE_MANUFACTURER',
                key: 'DeviceManufacturerName'
            }
        },
        DeviceUrlPicture: {
            type: DataTypes.TEXT,
            allowNull: true, // change if you rollback
            defaultValue: undefined
        }
    }, {
        tableName: 'DEVICE_MODEL'
    });
};

I think sequelize will only use the first PK part, which will never be changed.

Or maybe I’m totally wrong and I have to do it like you are instructing me 😄

How is this supposed to work? From which version?

Could someone post a complete example? Thanks

user.set('id', 42, { raw: true });
user.changed('id', true);

I’ll try that out. lol. maybe my PR is unneeded. And there I was all proud of myself for creating tests.

I’ll confirm that this works on my setup tomorrow. Assuming it is confirmed, I’ll make a unit test for it and then request a PR so the behavior is documented.

On May 2, 2016, at 12:03 AM, Mick Hansen notifications@github.com wrote:

It’s a safety check, you generally don’t want user provided values to edit the primary key. You can use raw: true to skip the check

— You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub https://github.com/sequelize/sequelize/issues/5827#issuecomment-216119620