How to Update Table Records Using Select Statement Results in SQL

Written by Yannick Brun

November 3, 2025

Looking to update table records using SELECT statement results? The most efficient approach is using an UPDATE with JOIN to directly connect your target table with the source data. This method offers superior performance and cleaner syntax compared to subqueries or complex MERGE operations for most scenarios.

πŸ’‘ Quick Answer: Use UPDATE target_table SET column = source.column FROM target_table INNER JOIN source_table ON condition for the most reliable and performant updates.

Method 1: UPDATE with JOIN (Recommended Approach)

The UPDATE with JOIN method directly connects your target table to the source data, making it both readable and efficient. Here’s the fundamental syntax:

UPDATE target_table
SET target_table.column1 = source.column1,
    target_table.column2 = source.column2
FROM target_table
INNER JOIN source_table AS source
    ON target_table.id = source.id
WHERE additional_conditions;

Real-World Example: Employee Salary Updates

Let’s say you need to update employee salaries from an HR import table:

-- Update employee salaries from import data
UPDATE employees
SET employees.salary = salary_import.new_salary,
    employees.last_updated = GETDATE()
FROM employees
INNER JOIN salary_import
    ON employees.employee_id = salary_import.employee_id
WHERE salary_import.effective_date <= GETDATE();
Database JOIN Syntax Support Key Differences
SQL Server βœ… Full FROM clause support Uses FROM after SET clause
MySQL βœ… Multi-table UPDATE JOIN comes after UPDATE clause
PostgreSQL βœ… UPDATE...FROM pattern FROM clause after WHERE

Method 2: UPDATE with Subquery

Subqueries work best for single-column updates or when you need complex filtering logic:

-- Update product prices from supplier catalog
UPDATE products
SET price = (
    SELECT supplier_catalog.unit_price
    FROM supplier_catalog
    WHERE supplier_catalog.product_code = products.sku
)
WHERE EXISTS (
    SELECT 1 
    FROM supplier_catalog
    WHERE supplier_catalog.product_code = products.sku
);
⚠️ Important: Always include an EXISTS clause with subquery updates to avoid setting values to NULL when no matching records are found.

Method 3: MERGE Statement (Advanced Synchronization)

MERGE handles complex scenarios where you need to insert, update, or delete records based on matching conditions:

-- Synchronize inventory levels from warehouse system
MERGE inventory AS target
USING warehouse_updates AS source
    ON target.product_id = source.product_id
WHEN MATCHED THEN
    UPDATE SET 
        target.quantity = source.current_stock,
        target.last_sync = GETDATE()
WHEN NOT MATCHED BY TARGET THEN
    INSERT (product_id, quantity, last_sync)
    VALUES (source.product_id, source.current_stock, GETDATE())
WHEN NOT MATCHED BY SOURCE THEN
    DELETE;

Database-Specific Implementations

MySQL Multi-Table UPDATE

UPDATE customers c
INNER JOIN address_updates au ON c.customer_id = au.customer_id
SET c.address = au.new_address,
    c.city = au.new_city
WHERE au.verified = 1;

PostgreSQL UPDATE...FROM

UPDATE orders
SET shipping_cost = rate_table.cost
FROM shipping_rates rate_table
WHERE orders.destination_zone = rate_table.zone
AND orders.weight <= rate_table.max_weight;

Performance Optimization Strategies

πŸš€ Index Optimization

  • JOIN columns: Ensure both tables have indexes on JOIN condition columns
  • WHERE clauses: Index any columns used in WHERE conditions
  • Composite indexes: Consider multi-column indexes for complex conditions

πŸ“Š Batch Processing Large Updates

-- Process in batches to avoid lock timeouts
DECLARE @BatchSize INT = 10000;
WHILE @@ROWCOUNT > 0
BEGIN
    UPDATE TOP(@BatchSize) target_table
    SET column1 = source.column1
    FROM target_table t
    INNER JOIN source_table s ON t.id = s.id
    WHERE t.processed = 0;
    
    -- Mark as processed
    UPDATE TOP(@BatchSize) target_table
    SET processed = 1
    WHERE processed = 0;
END

Common Pitfalls and Solutions

πŸ” Testing Strategy: Always run your UPDATE as a SELECT first to verify the results:

-- Test query first
SELECT t.id, t.current_value, s.new_value
FROM target_table t
INNER JOIN source_table s ON t.id = s.id
WHERE t.current_value != s.new_value;

Multiple Row Matches

Prevent unexpected results when source tables contain duplicate keys:

-- Use ROW_NUMBER() to handle duplicates
WITH ranked_source AS (
    SELECT *, 
           ROW_NUMBER() OVER (PARTITION BY id ORDER BY updated_date DESC) as rn
    FROM source_table
)
UPDATE target_table
SET column1 = rs.column1
FROM target_table t
INNER JOIN ranked_source rs ON t.id = rs.id
WHERE rs.rn = 1;

Best Practices Checklist

  • βœ… Backup critical data before major updates
  • βœ… Use transactions for rollback capability
  • βœ… Test in staging environment first
  • βœ… Verify row counts match expectations
  • βœ… Monitor execution plans for performance issues
  • βœ… Handle NULL values explicitly in JOIN conditions

Frequently Asked Questions

❓ Can I update multiple columns from different tables in one statement?

Yes, you can update multiple columns from different source tables using multiple JOINs:

UPDATE orders o
SET o.customer_name = c.name,
    o.shipping_cost = s.rate
FROM orders o
INNER JOIN customers c ON o.customer_id = c.id
INNER JOIN shipping_rates s ON o.shipping_zone = s.zone;

❓ What happens if the JOIN finds no matching records?

When using INNER JOIN, only rows with matches will be updated. Rows without matches remain unchanged. Use LEFT JOIN if you want to update all rows in the target table.

❓ How do I handle transaction rollback for large updates?

Wrap your updates in explicit transactions with proper error handling:

BEGIN TRANSACTION;
BEGIN TRY
    UPDATE target_table SET column1 = source.column1
    FROM target_table t
    INNER JOIN source_table s ON t.id = s.id;
    
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION;
    THROW;
END CATCH;

❓ Which method performs better: JOIN or subquery?

UPDATE with JOIN typically performs better because:

  • The database optimizer can create better execution plans
  • Joins are processed once, while subqueries may execute for each row
  • Index usage is more efficient with JOINs

For more advanced SQL techniques, check out Microsoft's official UPDATE documentation or explore PostgreSQL's UPDATE syntax guide.

🎯 Key Takeaway: UPDATE with JOIN provides the most efficient and readable solution for most update scenarios. Start with this method, test thoroughly, and optimize with proper indexing for production environments.

Hi, I’m Yannick Brun, the creator of ListPoint.co.uk.
I’m a software developer passionate about building smart, reliable, and efficient digital solutions. For me, coding is not just a job β€” it’s a craft that blends creativity, logic, and problem-solving.

Leave a Comment