En SQLite, un AUTOINCREMENT
columna es aquella que utiliza un valor incrementado automáticamente para cada fila que se inserta en la tabla.
Hay un par de formas de crear un AUTOINCREMENT
columna:
- Puedes crearlo implícitamente cuando defines la columna como
INTEGER PRIMARY KEY
. - Puedes crearlo explícitamente con
AUTOINCREMENT
palabra clave. Una desventaja de este método es que utiliza CPU, memoria, espacio en disco y sobrecarga de E/S de disco adicionales.
Ambos métodos hacen que la columna use un valor incremental cada vez que se inserta una nueva fila con NULL
en esa columna.
Sin embargo, existen algunas diferencias sutiles entre cómo funciona cada método.
Sin la palabra clave AUTOINCREMENT
Cuando declaras una columna como INTEGER PRIMARY KEY
, se incrementará automáticamente. Por lo tanto, en realidad no necesita usar el AUTOINCREMENT
palabra clave para tener una columna que use un valor que se incrementa automáticamente para cada fila.
Cuando haces esto, cualquier NULL
los valores se convierten en el ROWID
actual . En otras palabras, si inserta NULL
en esa columna, se convertirá al ROWID
actual .
En realidad, la forma en que funciona es que la columna se convierte en un alias para ROWID
. Puede acceder al ROWID
valor mediante el uso de cualquiera de los cuatro nombres; el nombre de la columna, ROWID
, _ROWID_
o OID
.
Un beneficio de omitir AUTOINCREMENT
La palabra clave es que reduce la CPU, la memoria, el espacio en disco y la sobrecarga de E/S del disco.
Sin embargo, una desventaja importante es que no puede garantizar que todas las filas se incrementen en orden ascendente. Esto se debe a la forma en que funciona el incremento automático cuando se omite AUTOINCREMENT
palabra clave versus usar esa palabra clave.
Cuando omite el AUTOINCREMENT
palabra clave, una vez ROWID
es igual al entero más grande posible (9223372036854775807), SQLite intentará encontrar un ROWID
positivo no utilizado al azar.
Sin embargo, siempre que nunca use el máximo ROWID
valor y nunca elimina la entrada en la tabla con el mayor ROWID
, este método generará un ROWID
único que aumenta monótonamente s.
Con la palabra clave AUTOINCREMENTO
También puede crear columnas de incremento automático de forma explícita. Para hacer esto, use el AUTOINCREMENT
palabra clave.
Cuando usa este método, se usa un algoritmo ligeramente diferente para determinar el valor de incremento automático.
Cuando usas el AUTOINCREMENT
palabra clave, el ROWID
elegido para la nueva fila es al menos uno más grande que el mayor ROWID
que ha alguna vez antes existía en esa misma tabla.
En otras palabras, no volverá atrás y reutilizará ROWID
previamente eliminado valores. Una vez que el ROWID
más grande posible se ha insertado, no se permiten nuevas inserciones. Cualquier intento de insertar una nueva fila fallará con un SQLITE_FULL
error.
Por lo tanto, usar este método garantiza que ROWID
s son monótonamente crecientes. En otras palabras, puede confiar en este método para tener ROWID
s en orden ascendente.
Sin embargo, esto no significa que los valores siempre se incrementarán en 1. Simplemente significa que nunca disminuirán.
Ejemplo
Aquí hay un ejemplo para demostrar la diferencia entre definir implícita y explícitamente una columna de incremento automático.
CREATE TABLE Cats(
CatId INTEGER PRIMARY KEY,
CatName
);
CREATE TABLE Dogs(
DogId INTEGER PRIMARY KEY AUTOINCREMENT,
DogName
);
INSERT INTO Cats VALUES
( NULL, 'Brush' ),
( NULL, 'Scarcat' ),
( NULL, 'Flutter' );
INSERT INTO Dogs VALUES
( NULL, 'Yelp' ),
( NULL, 'Woofer' ),
( NULL, 'Fluff' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Resultado inicial:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 3 Fluff
Ahora eliminemos la última fila de cada tabla, insertemos las filas nuevamente y luego seleccionemos el resultado:
DELETE FROM Cats WHERE CatId = 3;
DELETE FROM Dogs WHERE DogId = 3;
INSERT INTO Cats VALUES ( NULL, 'New Flutter' );
INSERT INTO Dogs VALUES ( NULL, 'New Fluff' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Resultado:
CatId CatName ---------- ---------- 1 Brush 2 Scarcat 3 New Flutter DogId DogName ---------- ---------- 1 Yelp 2 Woofer 4 New Fluff
En resumen, los gatos la tabla fue creada sin el AUTOINCREMENT
palabra clave y Perros la tabla fue creada con el AUTOINCREMENT
palabra clave.
Después de eliminar la última fila de Cats tabla, el siguiente INSERT
la operación resultó en el mismo ROWID
siendo reutilizado para esa fila.
Sin embargo, los Perros la mesa era diferente. Fue creado con el AUTOINCREMENT
palabra clave y por lo tanto no puede reutilizar el valor anterior. Simplemente aumenta al siguiente valor, dejando un espacio en la numeración.
ROWID máximo
Podemos llevar el ejemplo anterior un paso más allá e insertar una nueva fila usando explícitamente el máximo ROWID
posible.
INSERT INTO Cats VALUES ( 9223372036854775807, 'Magnus' );
INSERT INTO Dogs VALUES ( 9223372036854775807, 'Maximus' );
SELECT * FROM Cats;
SELECT * FROM Dogs;
Resultado:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 9223372036854775807 Magnus DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
Bien, ambas tablas usan el entero más grande posible como su ROWID
más grande valores.
Veamos qué sucede cuando intento insertar una nueva fila en cada tabla (sin especificar explícitamente un valor para las columnas de incremento automático).
Insertar en los Gatos tabla:
INSERT INTO Cats VALUES ( NULL, 'Scratchy' );
SELECT * FROM Cats;
Resultado:
CatId CatName -------------------- -------------------- 1 Brush 2 Scarcat 3 New Flutter 267244677462397326 Scratchy 9223372036854775807 Magnus
Entonces los gatos la mesa fue exitosa. Sin embargo, observe que el nuevo valor de incremento automático es menor que el valor anterior (no tiene otra opción).
Sin tener ninguna otra columna para registrar la fecha/hora en que se insertó/actualizó la fila, se podría suponer incorrectamente que Magnus se insertó después de Scratchy .
Ahora intentemos insertar una nueva fila en Perros tabla:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Resultado:
Error: database or disk is full
Entonces obtenemos un resultado diferente a los Cats mesa.
Recibí este error porque el ROWID
más grande posible ya se está utilizando en la tabla, y porque esta tabla se creó con AUTOINCREMENT
palabra clave, no volverá atrás y buscará un ROWID
no utilizado valor.
SELECT * FROM Dogs;
Resultado:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 9223372036854775807 Maximus
Además, seguiré recibiendo este error, incluso si elimino Maximus de la tabla (es decir, el perro con el máximo ROWID
valor).
Intentémoslo:
DELETE FROM Dogs WHERE DogId = 9223372036854775807;
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Resultado:
Error: database or disk is full
Así que no solo recibimos un error, sino que también eliminé Maximus :
SELECT * FROM Dogs;
Resultado:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff
Es importante tener en cuenta que esto sucederá incluso si cambio el ROWID
valor a un valor inferior. El hecho de que ya haya usado un ROWID de 9223372036854775807 significa que AUTOINCREMENT
ya no se incrementará automáticamente.
Esto se debe a que AUTOINCREMENT
solo usa valores que son al menos uno más altos que cualquier valor que haya existido antes en esa misma tabla .
De ahora en adelante, si quisiera continuar insertando valores en esta columna, necesitaría insertar explícitamente el valor. Esto supone que no tengo ya 9223372036854775807 filas en la tabla.
Volvamos a insertar Maximus con un ROWID
menor y vuelve a intentarlo:
INSERT INTO Dogs VALUES ( 5, 'Maximus' );
SELECT * FROM Dogs;
Resultado:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus
Ahora intentemos insertar Lickable una vez más, usando AUTOINCREMENT
:
INSERT INTO Dogs VALUES ( NULL, 'Lickable' );
Resultado:
Error: database or disk is full
Entonces, aunque eliminé la fila que contiene el máximo ROWID
valor de 9223372036854775807, todavía me impide incrementar automáticamente la columna.
Así es exactamente como fue diseñado. El ROWID
máximo ha estado previamente en esta tabla y entonces AUTOINCREMENT
no se incrementará automáticamente de nuevo en esa tabla.
La única forma de agregar una nueva fila a esa tabla es insertar manualmente el ROWID
valor.
INSERT INTO Dogs VALUES (6, 'Lickable');
SELECT * FROM Dogs;
Resultado:
DogId DogName -------------------- -------------------- 1 Yelp 2 Woofer 4 New Fluff 5 Maximus 6 Lickable