sql >> Base de Datos >  >> RDS >> SQLite

Cómo funciona AUTOINCREMENTO en SQLite

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