根据其他列更新列

Update column based on other columns

我正在使用 ExpressJS 和 SQLite 构建一个简单的 API。

我正在添加一个 router.patch 方法,该方法将使用 id 作为主键更新 API 数据库中的数据条目。在我的数据库中,有一个名为 score 的列,由其他列的值及其整数类型的值的总和填充。

我需要我的方法来更新数据库中的这些列中的一个或多个,这些列也应该更新分数列以反映新值。

这是目前的方法:

router.patch('/cars/:id', (req, res) => {
    try {
       let sql = `UPDATE cars SET email = COALESCE(?,email), name = COALESCE(?,name), year = COALESCE(?,year), make = COALESCE(?,make), model = COALESCE(?,model), racer_turbo = COALESCE(?,racer_turbo), racer_supercharged = COALESCE(?,racer_supercharged), racer_performance = COALESCE(?,racer_performance), racer_horsepower = COALESCE(?,racer_horsepower), car_overall = COALESCE(?,car_overall), engine_modifications = COALESCE(?,engine_modifications), engine_performance = COALESCE(?,engine_performance), engine_chrome = COALESCE(?,engine_chrome), engine_detailing = COALESCE(?,engine_detailing), engine_cleanliness = COALESCE(?,engine_cleanliness), body_frame_undercarriage = COALESCE(?,body_frame_undercarriage), body_frame_suspension = COALESCE(?,body_frame_suspension), body_frame_chrome = COALESCE(?,body_frame_chrome), body_frame_detailing = COALESCE(?,body_frame_detailing), body_frame_cleanliness = COALESCE(?,body_frame_cleanliness), mods_paint = COALESCE(?,mods_paint), mods_body = COALESCE(?,mods_body), mods_wrap = COALESCE(?,mods_wrap), mods_rims = COALESCE(?,mods_rims), mods_interior = COALESCE(?,mods_interior), mods_other = COALESCE(?,mods_other), mods_ice = COALESCE(?,mods_ice), mods_aftermarket = COALESCE(?,mods_aftermarket), mods_wip = COALESCE(?,mods_wip), mods_overall = COALESCE(?,mods_overall) where car_id = ?`
       let params = [req.body.email,req.body.name,req.body.year,req.body.make,req.body.model,req.body.racer_turbo,req.body.racer_supercharged,req.body.racer_performance,req.body.racer_horsepower,req.body.car_overall,req.body.engine_modificationsreq.body.engine_performancereq.body.engine_chromereq.body.engine_detailingreq.body.engine_cleanlinessreq.body.body_frame_undercarriagereq.body.body_frame_suspensionreq.body.body_frame_chromereq.body.body_frame_detailingreq.body.body_frame_cleanlinessreq.body.mods_paintreq.body.mods_bodyreq.body.mods_wrapreq.body.mods_rimsreq.body.mods_interiorreq.body.mods_otherreq.body.mods_icereq.body.mods_aftermarketreq.body.mods_wipreq.body.mods_overallreq.params.id]
        db.run(sql, params, (err, row) => {
            res.status(200).json({
                message: 'success',
                data: {
                    car_id: req.params.id,
                    updates: req.body
                }
            })
        })
    // Catch error
    } catch(error) {
        // Log the error to the console
        console.log(error.message.red.bold)

        // Return a server error code and message
        res.status(500).json({
            message: 'Not found'
        })
    }
})

该方法按预期工作,因为它会更新“racer_turbo”或“engine_chrome”等列的值。这些更改会反映在数据库中。但是,修改后的每个条目的得分列并没有改变,它仍然显示旧值。我不确定如何修改我的代码以确保分数也更新。

这也是我的 sqlite3 数据库配置代码,以防它有助于描绘更清晰的画面。

// Importing sqlite3
const sqlite3 = require('sqlite3')
// Importing path
const path = require('path')
// Importing csvtojson
const csv = require('csvtojson')
// Path to config file
const config = require('../config')
// Path to data.csv file
const DATA_CSV = path.join(__dirname, '../data/data.csv')

// Enabling colors
config.colors.enable()

let db = new sqlite3.Database(config.database_name, (err) => {
    // If we encounter an error while creating the database
    if (err) {
        // Log the error message
        console.error(err.message.red)

        // Throw the error as well
        throw err
    // Otherwise proceed with database creation
    } 
    else {
        // Alert the user that they've successfully connected to the database
        console.log('Connected to database...'.blue)

        // Creating the cars table within our database with the columns from the CSV file
        db.run(`CREATE TABLE cars (
            car_id INT PRIMARY KEY,
            email TEXT UNIQUE,
            name TEXT,
            year INT,
            make TEXT,
            model TEXT,
            racer_turbo INT,
            racer_supercharged INT,
            racer_performance INT,
            racer_horsepower INT,
            car_overall INT,
            engine_modifications INT,
            engine_performance INT,
            engine_chrome INT,
            engine_detailing INT,
            engine_cleanliness INT,
            body_frame_undercarriage INT,
            body_frame_suspension INT,
            body_frame_chrome INT,
            body_frame_detailing INT,
            body_frame_cleanliness INT,
            mods_paint INT,
            mods_body INT,
            mods_wrap INT,
            mods_rims INT,
            mods_interior INT,
            mods_other INT,
            mods_ice INT,
            mods_aftermarket INT,
            mods_wip INT,
            mods_overall INT,
            score INT
            )`,
        (err) => {
            // If we get an error
            if (err) {
                // Console log the eror
                console.log(err.message.red)
            } 
            // Otherwise add the data from our csv file to the database cars table
            else {
                // Use the csvtojson package to convert the csv data into json format
                csv().fromFile(DATA_CSV)
                .then(data => {
                    // SQL Insert query command to put data from the columns into the database table
                    let insert = 'INSERT INTO cars (Car_ID, Email, Name, Year, Make, Model, Racer_Turbo, Racer_Supercharged, Racer_Performance, Racer_Horsepower, Car_Overall, Engine_Modifications, Engine_Performance, Engine_Chrome, Engine_Detailing, Engine_Cleanliness, Body_Frame_Undercarriage, Body_Frame_Suspension, Body_Frame_Chrome, Body_Frame_Detailing, Body_Frame_Cleanliness, Mods_Paint, Mods_Body, Mods_Wrap, Mods_Rims, Mods_Interior, Mods_Other, Mods_ICE, Mods_Aftermarket, Mods_WIP, Mods_Overall, Score) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)';
                    
                    // Loop through all rows inside the csv file and add them into the table
                    for(const entry of data) {
                        // Calculating entry score
                        let score = [parseInt(entry.Racer_Turbo) + parseInt(entry.Racer_Supercharged) + parseInt(entry.Racer_Performance) + parseInt(entry.Racer_Horsepower) + parseInt(entry.Car_Overall) + parseInt(entry.Engine_Modifications) + parseInt(entry.Engine_Performance) + parseInt(entry.Engine_Chrome) + parseInt(entry.Engine_Detailing) + parseInt(entry.Engine_Cleanliness) + parseInt(entry.Body_Frame_Undercarriage) + parseInt(entry.Body_Frame_Suspension) + parseInt(entry.Body_Frame_Chrome) + parseInt(entry.Body_Frame_Detailing) + parseInt(entry.Body_Frame_Cleanliness) + parseInt(entry.Mods_Paint) + parseInt(entry.Mods_Body) + parseInt(entry.Mods_Wrap) + parseInt(entry.Mods_Rims) + parseInt(entry.Mods_Interior) + parseInt(entry.Mods_Other) + parseInt(entry.Mods_ICE) + parseInt(entry.Mods_Aftermarket) + parseInt(entry.Mods_WIP) + parseInt(entry.Mods_Overall)]
                    
                        // Use the run function from sqlite database
                        db.run(insert, [
                            entry.Car_ID, entry.Email, entry.Name, entry.Year, entry.Make, entry.Model, entry.Racer_Turbo, entry.Racer_Supercharged, entry.Racer_Performance, entry.Racer_Horsepower, entry.Car_Overall, entry.Engine_Modifications, entry.Engine_Performance, entry.Engine_Chrome, entry.Engine_Detailing, entry.Engine_Cleanliness, entry.Body_Frame_Undercarriage, entry.Body_Frame_Suspension, entry.Body_Frame_Chrome, entry.Body_Frame_Detailing, entry.Body_Frame_Cleanliness, entry.Mods_Paint, entry.Mods_Body, entry.Mods_Wrap, entry.Mods_Rims, entry.Mods_Interior, entry.Mods_Other, entry.Mods_ICE, entry.Mods_Aftermarket, entry.Mods_WIP, entry.Mods_Overall,
                            score
                        ]);
                    }
                }).catch(err => {
                    // log any error we might encounter if any
                    console.log(err);
                });
            }
        });  
    }
});

// Export our created database
module.exports = db

非常感谢任何帮助,因为我很困惑。

如果您的 SQLite 版本是 3.31.0,您可以将列 score 定义为 generated column:

CREATE TABLE cars (
  car_id INT PRIMARY KEY,
  email TEXT UNIQUE,
  .......................          
  score INT GENERATED ALWAYS AS (col1 + col2 + .....) VIRTUAL -- or STORED if you want the value stored in the table 
);

col1 + col2 + .....改为计算列score的值的表达式。

对于以前版本的 SQLite,要么使用 trigger,要么在 UPDATE 语句中更新列 score