Fondamentalmente è necessario inserire tali query nelle procedure archiviate a causa di alcune limitazioni su LIMIT . Non è possibile utilizzare selezioni secondarie o variabili in sql semplice. Nelle stored procedure è possibile utilizzare le variabili.
Funziona, sfortunatamente non posso mostrarlo in sqlfiddle perché sembrano avere un supporto limitato per le stored procedure.
drop procedure if exists all_but_3;
delimiter //
create procedure all_but_3()
begin
declare v_max bigint unsigned default ~0;
select * from your_table limit 3, v_max;
end//
delimiter ;
drop procedure if exists last_3;
delimiter //
create procedure last_3()
begin
declare v_max bigint;
declare v_mid bigint;
select count(*) from your_table into v_max;
set v_mid := v_max - 3;
select * from your_table limit v_mid, v_max;
end//
delimiter ;
call all_but_3();
call last_3();
Elaborazione sugli indici cluster di InnoDB
Dopo le discussioni in una delle altre risposte con @fthiella, ho deciso di approfondire alcuni su come questo può funzionare.
Una tabella che utilizza InnoDB come motore avrà sempre un indice cluster. Sempre. È il modo in cui i dati vengono archiviati in InnoDB e non è in alcun modo possibile creare una tabella senza un indice cluster.
InnoDB sceglierà la chiave primaria se è presente uno o il primo indice univoco con tutte le colonne impostate su non null. Se non esiste un tale indice, InnoDB creerà una colonna nascosta con un ID riga. Questo ID riga funziona in modo simile all'incremento automatico e se aiuta a pensarlo come una colonna invisibile con incremento automatico, penso che vada bene.
Inoltre InnoDB restituirà righe in base all'indice utilizzato. Utilizzerà sempre alcuni indici (l'unico modo per recuperare i dati consiste nell'utilizzare un indice secondario, l'indice cluster o una combinazione), quindi nel caso in cui non ci siano indici creati in modo esplicito le righe vengono restituite dall'indice cluster nascosto.
Ciò significa che una query su una tabella senza chiave primaria e senza indici univoci con tutte le colonne impostate su non null e senza ORDER BY restituirà le righe nell'ordine in cui sono state inserite.
Questo è il caso di questa domanda e la base per la mia e molte altre risposte.
Non voglio dire che questo sia un buon modo per lavorare con i dati. Ecco alcune cose a cui dovresti pensare prima di utilizzare questa soluzione:
- Se viene creato un indice che può essere utilizzato come indice cluster, la tabella verrà riscritta per utilizzare quell'indice e così facendo ordinerà i dati su disco. Se l'indice viene successivamente eliminato, l'ordine di inserimento originale viene perso e non può essere recuperato.
- Se viene creato un indice, anche se non è univoco, potrebbe essere scelto dall'ottimizzatore da utilizzare e le righe verranno invece ordinate in base a quell'indice.
Tutto questo è documentato e per 5.5 è il terzo punto elenco su questa pagina