MySQL Error 1093 — Why Can't I Query the Updated Table in a Subquery?
Architectural rationale behind Error 1093, derived table workarounds, optimizer merge pitfalls, MySQL 8 CTEs, and why physical temp table copying is harmful.
Operational Verification & Reliability Metadata
The error string is a symptom, not the root cause. Do not restart the server blindly. Run the diagnostic queries below to pinpoint the actual failure mode.
▸Symptom
ERROR 1093 (HY000): You can't specify target table 'siparis' for update in FROM clauseTypical SQL statement triggering this failure:
UPDATE orders
SET status = 'cancelled'
WHERE id IN (
SELECT id FROM orders WHERE total = 0 AND created_at < NOW() - INTERVAL 30 DAY
);The query attempts to mutate a table (UPDATE) while concurrently referencing that same relation in a subquery filter (SELECT). While PostgreSQL, Oracle, and SQL Server permit this construct, MySQL aborts execution immediately with ERROR 1093.
▸Architectural Rationale Behind the Restriction
This restriction is a deliberate design choice protecting data consistency and replication integrity:
- 1Mid-Stream Result Mutation: MySQL processes subquery evaluation iteratively during the row update cycle. Reading from the target relation while updating it alters the qualifying row set mid-flight.
- 2Replication Indeterminism: Under Statement-Based Replication (SBR), evaluating mutating subqueries can result in different execution sequences on replicas, causing silent data divergence between Primary and Secondary nodes.
▸Three Verified Production Workarounds
1. Materialization via Derived Tables
Nesting the subquery within an additional SELECT layer forces MySQL to materialize the intermediate dataset into memory before initiating table mutations:
UPDATE orders
SET status = 'cancelled'
WHERE id IN (
SELECT id FROM (
SELECT id FROM orders WHERE total = 0 AND created_at < NOW() - INTERVAL 30 DAY
) AS target_subset
);/*+ NO_MERGE(target_subset) */ optimizer hint:
``sql
UPDATE orders SET status = 'cancelled'
WHERE id IN (
SELECT /*+ NO_MERGE(target_subset) */ id FROM (
SELECT id FROM orders WHERE total = 0
) AS target_subset
);
2. Multi-Table JOIN Syntax (Recommended Best Practice)
The multi-table UPDATE ... JOIN construct is cleaner, yields deterministic execution plans, and avoids subquery nesting complexity:
UPDATE orders o
JOIN (
SELECT id FROM orders WHERE total = 0 AND created_at < NOW() - INTERVAL 30 DAY
) sub ON sub.id = o.id
SET o.status = 'cancelled';3. Common Table Expressions (MySQL 8.0+ CTE)
For modern MySQL 8.0 deployments, CTE syntax offers superior readability and maintainability:
WITH target_records AS (
SELECT id FROM orders WHERE total = 0 AND created_at < NOW() - INTERVAL 30 DAY
)
UPDATE orders o
JOIN target_records tr ON tr.id = o.id
SET o.status = 'cancelled';▸Harmful Anti-Pattern: Physical Temporary Table Copies
A common pitfall is creating temporary physical tables to bypass the limitation. This is detrimental on production workloads:
- •Incurs heavy disk I/O and buffer pool churn.
- •Prolongs table lock duration during the copying phase.
- •Introduces race conditions: Rows modified between the snapshot and the update create phantom inconsistencies.
▸Behavior Variations Across DML Constructs
- •`DELETE` Operations:
DELETE FROM orders WHERE id IN (SELECT id FROM orders ...)triggers the exact same 1093 error; apply the multi-tableDELETE ... JOINpattern to resolve it. - •`INSERT INTO ... SELECT`: MySQL explicitly permits reading from and writing to the same table in
INSERToperations without throwing 1093. - •Scalar Subquery Updates:
UPDATE orders SET total = (SELECT MAX(total) FROM orders)also encounters Error 1093.
▸Related Error Guides & Hub Links
- •MySQL Error 1451 Cannot Delete Parent Row (H-38) — Foreign key delete constraints
- •MySQL Error 1452 Foreign Key Constraint (H-14) — Missing parent records
- •MySQL Deadlock Found 1213 (H-05) — Concurrent transaction lock resolution
- •MySQL Hub — MySQL performance tuning and architecture
Other Database Error Triage Playbooks
Other battle-tested diagnostic guides for high-severity database errors.
MySQL ERROR 1045 Access denied: root Password Reset Guide
Four causes of MySQL 1045, meaning of using password: YES/NO, and safe credential recovery via --init-file.
MySQL Deadlock ERROR 1213: Graph Analysis and Permanent Prevention
Root causes of MySQL 1213 deadlock, parsing LATEST DETECTED DEADLOCK output, gap lock concurrency issues, and resilient application retry design.
MySQL Lock wait timeout exceeded: Finding Blocking Sessions
Finding the blocking transaction using performance_schema, safe KILL decision matrices, and permanent locking reduction.