You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sequelize插入时自动添加不存在列building_building_id报错求助

问题描述

使用Sequelize 6.13.0向PostgreSQL的property表插入数据,执行代码如下:

await Property.create(
    {
        clikalia_id: 1,
        property_type_id: PROPERTY_TYPES.EDIFICIO,
        street: newBuilding.street,
        number: newBuilding.number,
        zipcode: newBuilding.zipcode,
        location: point,
        owner_type: newBuilding.owner_type,
        uv_crm_id: newBuilding.uv_crm_id,
        easybroker_id: newBuilding.easybroker_id,
        uv: newBuilding.uv,
        stair: 0,
        door: 0,
        block: 0,
        inner_number: 0,
        floor: 0,
    }
);

执行时Sequelize会自动添加building_building_id列,因该列在数据库中不存在抛出异常。重启服务器后问题暂时消失,但会再次出现。需要解决该问题,避免频繁重启服务器,怀疑是Building表模型定义有误。

现有模型定义

Building模型

const Building = sequelizeSells.define(
    'building',
    {
        building_id: {
            type: DataTypes.UUID,
            primaryKey: true,
            references: {
                model: Property,
                key: 'id',
                deferrable: Deferrable.INITIALLY_IMMEDIATE,
            },
        },
        property_id: {
            type: DataTypes.UUID,
            primaryKey: true,
            references: {
                model: Property,
                key: 'id',
                deferrable: Deferrable.INITIALLY_IMMEDIATE,
            },
        },
    },
    {
        freezeTableName: true,
        timestamps: false,
        createdAt: false,
        updatedAt: false,
    }
);

export default Building;

Property模型

const Property = sequelizeSells.define(
    'property',
    {
        id: {
            type: DataTypes.UUID,
            primaryKey: true,
            defaultValue: DataTypes.UUIDV4,
        },
        clikalia_id: {
            type: DataTypes.INTEGER,
        },
        property_type_id: {
            type: DataTypes.INTEGER,
        },
        street: {
            type: DataTypes.STRING,
        },
        number: {
            type: DataTypes.STRING,
        },
        stair: {
            type: DataTypes.STRING,
        },
        door: {
            type: DataTypes.STRING,
        },
        block: {
            type: DataTypes.STRING,
        },
        inner_number: {
            type: DataTypes.STRING,
        },
        uv: {
            type: DataTypes.STRING,
        },
        floor: {
            type: DataTypes.INTEGER,
        },
        location: {
            type: DataTypes.GEOGRAPHY,
        },
        zipcode: {
            type: DataTypes.STRING,
        },
        owner_type: {
            type: DataTypes.STRING,
        },
        created_at: {
            type: DataTypes.TIME,
        },
        updated_at: {
            type: DataTypes.TIME,
        },
        uv_crm_id: {
            type: DataTypes.NUMBER,
        },
        easybroker_id: {
            type: DataTypes.STRING,
        },
    },
    {
        freezeTableName: true,
        timestamps: false,
        createdAt: true,
        updatedAt: true,
    }
);

export default Property;
解决方案

1. 修正Building模型的主键与外键定义

当前Building模型中building_id作为主键同时引用Property的id,这种配置会让Sequelize错误推断关联关系,自动生成额外的外键列。正确的做法是将building_id设为自身独立主键,property_id作为外键关联Property:

const Building = sequelizeSells.define(
    'building',
    {
        building_id: {
            type: DataTypes.UUID,
            primaryKey: true,
            defaultValue: DataTypes.UUIDV4, // 独立生成主键,不再引用Property
        },
        property_id: {
            type: DataTypes.UUID,
            allowNull: false,
            references: {
                model: 'property', // 使用表名确保引用正确,避免模型加载顺序问题
                key: 'id',
                deferrable: Deferrable.INITIALLY_IMMEDIATE,
            },
        },
    },
    {
        freezeTableName: true,
        timestamps: false,
    }
);

export default Building;

2. 显式定义模型关联关系

在模型初始化时添加关联定义(通常在专门的关联文件或模型的associate方法中),明确Property与Building的关系:

// 假设在关联配置文件中
Building.belongsTo(Property, { foreignKey: 'property_id', targetKey: 'id' });
Property.hasOne(Building, { foreignKey: 'property_id', sourceKey: 'id' });

3. 插入时显式指定字段

在Property.create调用中添加fields选项,强制Sequelize只插入指定字段,避免自动添加额外列:

await Property.create(
    {
        clikalia_id: 1,
        property_type_id: PROPERTY_TYPES.EDIFICIO,
        street: newBuilding.street,
        number: newBuilding.number,
        zipcode: newBuilding.zipcode,
        location: point,
        owner_type: newBuilding.owner_type,
        uv_crm_id: newBuilding.uv_crm_id,
        easybroker_id: newBuilding.easybroker_id,
        uv: newBuilding.uv,
        stair: 0,
        door: 0,
        block: 0,
        inner_number: 0,
        floor: 0,
    },
    { 
        fields: [
            'clikalia_id', 'property_type_id', 'street', 'number', 
            'zipcode', 'location', 'owner_type', 'uv_crm_id', 
            'easybroker_id', 'uv', 'stair', 'door', 'block', 
            'inner_number', 'floor'
        ] 
    }
);

4. 确保模型加载顺序正确

先加载Property模型,再加载Building模型,避免循环引用导致的缓存异常——这也是重启服务器暂时解决问题的原因(重启后加载顺序可能临时正确)。

内容的提问来源于stack exchange,提问作者Jorge López

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 15:33:34