Medium severityschema
MySQL Error:
1109
What does this error mean?
MySQL Error 1109 wordt gegooid wanneer een multi-table DELETE statement een tabelnaam of alias opsomt in het DELETE-doel die niet voorkomt in de FROM- of USING-clausule van diezelfde query. MySQL lost aliases op tijdens parsing: als `t1` niet eerder gedeclareerd is in de FROM/USING scope, stopt de query direct met een parse-fout — er worden geen rijen verwijderd. In data-pipelines duikt dit typisch op in dbt post-hooks, ADF Script activities, of stored procedures die opruimlogica bevatten na een load-stap. Het symptoom is een harde query-fout met SQLSTATE 42S02, de pipeline-run stopt en downstream modellen of afgeleide tabellen worden niet ververst.
Common causes
- 1Alias in DELETE-doellijst komt niet overeen met de alias in de FROM-clausule: `DELETE tbl1 FROM table1 AS t1 ...` faalt omdat `tbl1` nooit gedeclareerd is — de alias in het DELETE-doel moet letterlijk gelijk zijn aan de alias na AS.
- 2Verwisseling van USING- en FROM-syntax: bij `DELETE t1, t2 USING table1 t1 JOIN table2 t2 ...` moeten de aliasnamen in het USING-blok staan; wordt abusievelijk een FROM gebruikt dan vindt MySQL de alias niet.
- 3Typo of hoofdletterverschil in tabelnaam: op case-sensitive filesystems (Linux) is `Orders` een andere identifier dan `orders`; een DELETE die `Orders` targetet terwijl de FROM-clausule `orders` definieert geeft Error 1109.
- 4Multi-table DELETE gegenereerd door een ORM of templating-script met een variabele die leeg of null bleef: het DELETE-target wordt dan een lege string of een ongeldige identifier die niet matcht met de FROM-alias.
- 5Subquery als bron in de FROM-clausule krijgt geen alias mee, terwijl het DELETE-doel er wel naar verwijst: `DELETE sub FROM (SELECT id FROM staging) JOIN main ON ...` — de subquery heeft geen naam en is dus niet adresseerbaar als DELETE-target.
- 6Copy-paste van een DELETE-query uit een andere database (PostgreSQL, SQL Server) waarbij de syntax afwijkt van MySQL's multi-table DELETE-conventie; in MySQL moet het doel vóór FROM staan, in andere dialecten werkt dat anders.
- 7Stored procedure met een dynamische tabelnaam via PREPARE/EXECUTE waarbij de alias in de voorbereide SQL-string niet correct geïnterpoleerd wordt, waardoor de runtime-naam verschilt van de compile-time alias.
How to fix it
- 1Stap 1: Controleer de exacte alias-declaratie in de FROM/USING-clausule en zorg dat het DELETE-doel identiek is: `DELETE t1 FROM table1 AS t1 INNER JOIN table2 AS t2 ON t1.id = t2.ref_id WHERE t2.status = 'inactive';`
- 2Stap 2: Verifieer de query met EXPLAIN — hoewel EXPLAIN een DELETE niet uitvoert, toont MySQL bij syntaxfouten direct de fout zodat je de exacte positie in de query ziet: `EXPLAIN DELETE t1 FROM table1 t1 JOIN table2 t2 ON t1.id=t2.id WHERE t2.flag=1;`
- 3Stap 3: Herschrijf als single-table DELETE met een subquery als multi-table syntax verwarring geeft: `DELETE FROM table1 WHERE id IN (SELECT ref_id FROM table2 WHERE status = 'inactive');` — let op dat MySQL subqueries op dezelfde tabel in DELETE niet direct toestaat; gebruik dan een geneste subquery: `DELETE FROM table1 WHERE id IN (SELECT id FROM (SELECT ref_id AS id FROM table2 WHERE status='inactive') AS tmp);`
- 4Stap 4: Controleer in dbt of de post-hook de juiste Jinja-variabelen gebruikt: open het model-bestand en verifieer dat `{{ this }}` of een expliciete `ref()` correct wordt gerenderd naar de volledige tabelnaam inclusief schema; voer `dbt compile` uit en bekijk de gerenderde SQL in `target/compiled/`.
- 5Stap 5: In een ADF Script activity: open de activiteit, ga naar het tabblad Script, plak de query in een MySQL Workbench-sessie en voer hem uit met dezelfde serviceaccount-rechten om de exacte fout te reproduceren buiten ADF-context.
- 6Stap 6: Controleer stored procedures met `SHOW CREATE PROCEDURE procedure_naam\G` — zoek naar PREPARE/EXECUTE-blokken met dynamische SQL en log de geïnterpoleerde string met `SET @debug_sql = ...; SELECT @debug_sql;` voordat je EXECUTE aanroept.
- 7Stap 7: Zet `general_log = ON` tijdelijk in een testomgeving (`SET GLOBAL general_log = 'ON'; SET GLOBAL general_log_file='/tmp/mysql-general.log';`) en herhaal de falende operatie — het logbestand toont de letterlijke SQL die MySQL ontvangt, inclusief verkeerd geïnterpoleerde aliassen.
Example log output
ERROR 1109 (42S02): Unknown table 'tbl1' in MULTI DELETE
[ADF] Activity 'Delete_Staging_Rows' failed: MySqlException: Error Code: 1109. Unknown table 'staging_tbl' in MULTI DELETE, query: DELETE staging_tbl FROM staging AS stg JOIN ...
[dbt] Database Error in model cleanup_hook (models/staging/orders.sql): (mysql.connector.errors.DatabaseError) 1109 (42S02): Unknown table 'orders' in MULTI DELETE