SQL Server CRUD

How to UPDATE with JOIN in SQL Server (With Examples)

Update rows based on another table in SQL Server using FROM JOIN. Covers INNER JOIN, LEFT JOIN, OUTPUT clause, and CTE updates.

Mar 12, 2026 5 min read

Introduction

SQL Server uses a FROM clause for UPDATE JOINs — different from MySQL. This T-SQL syntax is powerful and supports features like OUTPUT and CTE-based updates.

UPDATE with FROM JOIN

SQL Server puts the JOIN in a FROM clause after SET — not between UPDATE and SET like MySQL.

-- Update product prices from a price list:
UPDATE p
SET p.price = pu.new_price,
    p.updated_at = GETDATE()
FROM products p
INNER JOIN price_updates pu ON p.sku = pu.sku;

Tip: The key difference from MySQL: SET comes before FROM in SQL Server.

UPDATE with OUTPUT (See What Changed)

OUTPUT clause shows you exactly which rows were modified — like PostgreSQL's RETURNING.

-- Update and see the changes:
UPDATE p
SET p.price = pu.new_price
OUTPUT
  inserted.sku,
  deleted.price AS old_price,
  inserted.price AS new_price
FROM products p
INNER JOIN price_updates pu ON p.sku = pu.sku;

Tip: deleted = old values, inserted = new values in the OUTPUT clause. Great for audit logging.

UPDATE with CTE

Use a CTE (Common Table Expression) for complex update logic — cleaner than nested subqueries.

-- Update using a CTE:
WITH customer_stats AS (
  SELECT
    customer_id,
    COUNT(*) AS order_count,
    SUM(amount) AS total_spent
  FROM orders
  GROUP BY customer_id
)
UPDATE c
SET c.total_orders = cs.order_count,
    c.lifetime_value = cs.total_spent
FROM customers c
INNER JOIN customer_stats cs ON c.id = cs.customer_id;

Tip: CTEs make complex UPDATE JOINs much more readable. You can even chain multiple CTEs.

UPDATE TOP N Rows

Limit how many rows are updated — useful for batch processing.

-- Update only the first 1000 rows:
UPDATE TOP (1000) o
SET o.status = 'processed'
FROM orders o
WHERE o.status = 'pending'
AND o.created_at < DATEADD(day, -30, GETDATE());

Tip: Use TOP in a loop to process large updates in batches, avoiding long-running transactions and lock escalation.

UPDATE with Subquery

Use a correlated subquery when you need to update based on aggregated data from the same table.

-- Set rank based on revenue:
UPDATE p
SET p.rank_in_category = sub.rnk
FROM products p
INNER JOIN (
  SELECT id, ROW_NUMBER() OVER (
    PARTITION BY category
    ORDER BY revenue DESC
  ) AS rnk
  FROM products
) sub ON p.id = sub.id;

Tip: Window functions in subqueries are perfect for calculating rankings, running totals, and percentiles in UPDATE statements.

Best Practices

  • Always use aliases (UPDATE p FROM products p) for clarity
  • Use OUTPUT clause for audit trails
  • Use CTE for complex update logic instead of nested subqueries
  • Batch large updates with TOP to avoid lock escalation
  • Test with SELECT first: replace UPDATE SET with SELECT to preview

Generate SQL Server Queries with AI2SQL

Skip the syntax lookup. Describe what you need in plain English and AI2SQL generates the correct SQL Server query instantly.

Try AI2SQL Free

No credit card required

Frequently Asked Questions

How do I update from another table in SQL Server?

Use UPDATE alias SET ... FROM table1 alias INNER JOIN table2 ON condition. Note: SET comes before FROM in T-SQL, unlike MySQL.

What is the OUTPUT clause in SQL Server UPDATE?

OUTPUT returns the old (deleted) and new (inserted) values of modified rows. It works like RETURNING in PostgreSQL.

Can AI2SQL generate T-SQL UPDATE queries?

Yes. Select SQL Server as your dialect and AI2SQL generates correct T-SQL with FROM JOIN, OUTPUT, and CTE syntax.

Generate SQL from Plain English

Stop memorizing syntax. Describe what you need and let AI2SQL write the query for you.

Try AI2SQL Free

No credit card required