Now let’s create an endpoint to update existing users.

The :id in the URL specifies which user to update.

PUT performs a full replacement of the resource - this means all fields (username AND email) must be provided to completely update the user. This uses the UPDATE SQL command to modify existing database records.

Returning the Updated User

Just like with creation, it’s standard practice to return the updated user back to the frontend. This allows the frontend to immediately see the changes without making a separate GET request.

Updating Users Endpoint

// Update a user (full replacement)
app.put("/users/:id", async (req, res) => {
  try {
    const userId = Number(req.params.id);
    const { username, email } = req.body;

    // Validate ID
    if (isNaN(userId)) {
      return res.status(400).json({
        error: "Invalid user ID",
      });
    }

    // Validate required fields
    if (!username || !email) {
      return res.status(400).json({
        error: "Username and email are required",
      });
    }

    // Update the user in the database
    const [result]: [ResultSetHeader, any] = await pool.execute(
      "UPDATE users SET username = ?, email = ? WHERE id = ?",
      [username, email, userId]
    );

    // Check if user was found and updated
    if (result.affectedRows === 0) {
      return res.status(404).json({
        error: "User not found",
      });
    }

    const user: User = { id: userId, username, email };
    res.json(user);
  } catch (error) {
    console.error("Database error:", error);
    res.status(500).json({
      error: "Failed to update user",
    });
  }
});

Understanding the PUT Code

How the Code Works

  1. UPDATE the user: We modify the existing user in the database with UPDATE SET.
  2. Construct the response object: We build the user object from the request data and the URL parameter ID.

Understanding the Database Result

const [result]: [ResultSetHeader, any] = await pool.execute(...);

Just like with POST, the UPDATE operation returns a ResultSetHeader with useful information:

  • affectedRows - How many rows were changed (0 means user not found, 1 means success).
  • changedRows - How many rows actually changed.
  • No insertId this time since we’re updating, not creating.

Building the Response

const user: User = { id: userId, username, email };

We create the user object by combining:

  • id: The user ID from the URL parameter (req.params.id).
  • username and email: The updated data from the request body.

Full Replacement

  • PUT replaces the entire resource (username AND email required).
  • All fields must be provided to completely update the user.

Checking if Update Succeeded

We use result.affectedRows to verify the update worked:

  • 1 means the user was found and updated successfully.
  • 0 means no user exists with that ID (return 404 Not Found).


Repo link

Tags: