Función NEXTVAL en PostgreSQL

Bilal Shahid 20 junio 2023
Función NEXTVAL en PostgreSQL

NEXTVAL() tiende a avanzar un objeto a otro valor y devolverlo. Los ‘OBJETOS DE SECUENCIA’ son solo tablas de una sola fila creadas a partir de ‘SECUENCIAS’ en PostgreSQL.

La función NEXTVAL() se define en FUNCIONES DE MANIPULACIÓN DE SECUENCIA.

nextval ( regclass ) ? bigint

REGCLASS se refiere al SEQUENCE OBJECT, y esta función tiende a devolver BIGINT. Ahora veamos algunas implementaciones posibles de esta función NEXTVAL() y cómo podemos usarla.

Ejemplo Práctico de NEXTVAL() en PostgreSQL

Uno de los usos de los IDENTIFICADORES DE SECUENCIA en PostgreSQL es cómo se pueden usar para obtener valores de identificador de fila únicos. Puede leer más sobre ellos en CREAR SECUENCIA URL.

Haremos un seguimiento del uso dado anteriormente y luego intentaremos implementar un sistema que pueda usar efectivamente la función NEXTVAL(). Arrancaremos PostgreSQL y crearemos una tabla simple llamada RANDOM_GEN (abreviatura de generador aleatorio).

CREATE TABLE RANDOM_GENE(
	val INT PRIMARY KEY
);

Hemos utilizado un VALOR simple como CLAVE PRINCIPAL en nuestra tabla, ya que será único y aleatorio. Ahora sigamos adelante y agreguemos algunos datos a esta tabla.

Por supuesto, el VAL debe ser RANDOM para usar el GENERADOR DE SECUENCIA en PostgreSQL. Nuestro tutorial utilizará un GENERADOR EN SERIE con valores incrementales para obtener VALOR ÚNICO.

CREATE SEQUENCE serial_num;

Y para utilizar los valores de este GENERADOR DE SECUENCIAS, podemos consultar una operación SELECCIONAR de esta tabla.

SELECT * from SERIAL_NUM;

Pero hay un problema. Si llamamos repetidamente a esta operación SELECCIONAR, tendemos a obtener el mismo valor del GENERADOR DE SECUENCIA.

Entonces, si tuviéramos que INSERTAR valores de esta SECUENCIA en nuestra tabla sin probar, habríamos terminado con valores duplicados.

Y aquí es donde entra la función NEXTVAL(). Podemos avanzar y avanzar el valor de este GENERADOR y luego ejecutar la operación SELECCIONAR para obtener los valores ascendentes.

Entonces podemos escribir:

SELECT * from NEXTVAL('serial_num');

Y esto devolverá la salida de la siguiente manera, digamos, 5 iteraciones.

Producción :

Iter      VAL
1          1
2          2
3          3
4          4
5          5

Entonces NEXTVAL(), como vimos, tiende a aumentar el GENERADOR DE SECUENCIA y avanzarlo. Entonces, cada vez que se llama a NEXTVAL() para la SECUENCIA pasada en su argumento, podemos imaginar que la SECUENCIA se apunte al siguiente valor ascendente.

Por lo tanto, ahora podemos llamar algo de la siguiente manera para una operación INSERT en nuestra tabla RANDOM_GEN.

INSERT INTO RANDOM_GENE values (NEXTVAL('SERIAL_NUM')), (NEXTVAL('SERIAL_NUM')), (NEXTVAL('SERIAL_NUM'));

Nuestra tabla ahora se verá de la siguiente manera.

Producción :

        val
1       1
2       2
3       3

Otra forma sencilla de lograr esto solo para la columna VALUE sería definir NEXTVAL() justo en la instrucción CREATE TABLE. Podemos escribir una consulta de la siguiente manera.

CREATE TABLE RANDOM_GENE(
	val INT primary key default NEXTVAL('SERIAL_NUM')
);

Hemos utilizado DEFAULT para definir el comportamiento predeterminado de esta columna VAL que obtiene valores del GENERADOR DE SECUENCIA. Por supuesto, lo anterior es inútil sin una columna secundaria, así que agreguemos una columna USER_NAME para definir los USUARIOS que reciben los valores RANDOM_GEN.

CREATE TABLE RANDOM_GENE(
	val INT primary key default NEXTVAL('SERIAL_NUM'),
        name TEXT
);

Ahora podemos escribir una instrucción INSERTAR de la siguiente manera.

INSERT into RANDOM_GENE (name) values ('John'), ('Marta'), ('Alex');

Esto INSERTARÁ los nombres dados en la consulta a nuestra tabla con los respectivos valores obtenidos en orden ascendente de nuestro GENERADOR DE SECUENCIAS. Si tendemos ahora a mirar la tabla, quedaría de la siguiente manera.

val     name
1	"John"
2	"Marta"
3	"Alex"

Por lo tanto, ahora hemos entendido completamente cómo funciona NEXTVAL(). Por ahora, veamos el funcionamiento de NEXTVAL() en diferentes entornos.

NEXTVAL() en diferentes entornos y circunstancias en PostgreSQL

El uso de NEXTVAL() tiende a incrementar el GENERADOR DE SECUENCIA cada vez que se llama. Por lo tanto, no tenemos que preocuparnos por los duplicados en este caso.

Una vez que se llama a NEXTVAL(), el GENERATOR avanza y calcula el siguiente valor. Cualquier otra consulta que se ejecute simultáneamente que llame a NEXTVAL() para la misma SECUENCIA obtendrá el valor único y completamente diferente del generador.

Por lo tanto, es eficiente y seguro usar NEXTVAL() para múltiples transacciones y procesos que pueden estar ejecutando consultas en un servidor de Postgres.

Brechas y diferencias de valor de NEXTVAL() en PostgreSQL

Un problema común que se encuentra en NEXTVAL() es la implementación estricta del avance. Una vez que la SECUENCIA avanza a los nuevos valores, es muy poco probable que regrese o incluso verifique si se ha utilizado un valor anterior o no.

Entonces, en caso de que tenga una tabla con una columna de valor ÚNICA y un NOMBRE, y de alguna manera el NOMBRE que está tratando de INSERTAR ya está presente en la tabla, puede obtener un error de violación. NEXTVAL() ya habría sido llamado en ese escenario.

Y la SECUENCIA avanzó a un valor, pero la violación impide la INSERCIÓN. Entonces, la próxima vez que se llame a INSERT, NEXTVAL() avanzará una vez más, y el valor anterior se omitirá por completo.

Lo mismo puede decirse de las operaciones ON CONFLICT o aquellas que no puedan ejecutarse correctamente. En el ejemplo que se muestra a continuación, use lo siguiente para llamar a un INSERTAR en la columna de la tabla NOMBRE.

name TEXT unique

Y luego, “INSERTAR” datos en nuestra tabla con un nombre duplicado intencional para ALEX con una consulta de la siguiente manera.

INSERT into RANDOM_GENE (name) values ('John'), ('Marta'), ('Alex'), ('Alex'), ('Mathew') on conflict (name) do nothing;

Hemos puesto EN CONFLICTO para evitar el error de violación duplicada y verificar nuestra tabla para el VALOR. La tabla ahora se ve de la siguiente manera.

val    name
1	"John"
2	"Marta"
3	"Alex"
5	"Mathew"

Puedes ver como no hay valor número 4 para la columna VAL. Y eso se debe a que la inserción duplicada de ALEX hizo avanzar el GENERADOR DE SECUENCIA pero no se INSERTÓ.

De ahí que para el nombre MATHEW, el valor ya estaba en 4, que luego avanzó a 5 para su INSERCIÓN.

Así que ahora esperamos que hayas entendido completamente cómo funciona NEXTVAL() y puedas implementarlo como quieras.

Bilal Shahid avatar Bilal Shahid avatar

Hello, I am Bilal, a research enthusiast who tends to break and make code from scratch. I dwell deep into the latest issues faced by the developer community and provide answers and different solutions. Apart from that, I am just another normal developer with a laptop, a mug of coffee, some biscuits and a thick spectacle!

GitHub

Artículo relacionado - PostgreSQL Function