Elimina in modo condizionale l'ultima riga in mysql

Aug 24 2020

Come faccio a eliminare in modo condizionale l'ultima riga in una tabella mysql?

me/my_machine@17:26:57>cat create_tables.sql
CREATE DATABASE IF NOT EXISTS test_db;

USE test_db;
CREATE TABLE IF NOT EXISTS err_hist_table (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  cl INT NOT NULL,
  usr VARCHAR(16),
  fault_code VARCHAR(10));

INSERT INTO err_hist_table (cl,usr,fault_code) VALUES (1,'pA','A'), (2,'pA','NULL'),(3,'pC','B'),(4,'pB','NULL');

I comandi SQL precedenti creano una tabella simile a questa:

MySQL [test_db]> SELECT * FROM err_hist_table;
+----+----+------+------------+
| id | cl | usr  | fault_code |
+----+----+------+------------+
|  1 |  1 | pA   | A          |
|  2 |  2 | pA   | NULL       |
|  3 |  3 | pC   | B          |
|  4 |  4 | pB   | NULL       |
+----+----+------+------------+
4 rows in set (0.00 sec)

Ora voglio DELETEl'ultima riga (valore più grande di id) solo quando il valore di fault_codeè NULL. Se non lo è NULL, voglio saltare l'eliminazione. Ai miei occhi da principiante sql, sembra che dovrebbe esserci qualcosa di semplice come:

SELECT * IF err_history_table.id=max(err_history_table) AND fault_code = 'NULL';

Non sono riuscito a trovare la mia risposta nella pagina dei documenti di mysql. C'è una soluzione semplice per qualcosa di simile?

Risposte

1 forpas Aug 24 2020 at 14:34

Puoi farlo con una sottoquery che restituisce la riga del massimo iddove controlli il valore di fault_code:

DELETE FROM err_hist_table
WHERE id = (
  SELECT id FROM (
    SELECT * FROM err_hist_table
    ORDER BY id DESC LIMIT 1
  ) t
  WHERE fault_code IS NULL
);

Guarda la demo .
Risultati:

| id  | cl  | usr | fault_code |
| --- | --- | --- | ---------- |
| 1   | 1   | pA  | A          |
| 2   | 2   | pA  |            |
| 3   | 3   | pC  | B          |
Marc Aug 24 2020 at 14:21

Non sono del tutto sicuro se questo è quello che vuoi, ma dovrebbe funzionare. Se hai una versione recente di MySQL dovresti essere in grado di utilizzare sottoquery, come questa:

DELETE FROM err_hist_table WHERE id = (SELECT MAX(id) FROM err_hist_table) AND fault_code IS NULL

Ovviamente non testato sul tuo tavolo specifico. Suggerirei anche di eseguire prima un SELECT per verificare che faccia ciò che ti aspetti.

billynoah Aug 25 2020 at 02:51

Vale la pena ricordare che puoi ottenere il risultato desiderato utilizzando un singolo JOIN, senza bisogno di una sotto-sottoquery e in un modo che mi sembra conciso e leggibile:

DELETE e1 FROM err_hist_table e1
JOIN (
    SELECT MAX(id) AS id
    FROM err_hist_table
) e2 USING (id)
WHERE e1.fault_code = 'NULL'

Maggiori informazioni sull'argomento dell'utilizzo dei join in una DELETEdichiarazione qui:https://dev.mysql.com/doc/refman/8.0/en/delete.html#idm45306662494864