PostgreSQL siguiente valor de las secuencias?

Estoy usando PostgreSQL para mi sitio web Codeigniter. Estoy usando productos de abarrotes para agregar, editar y eliminar operaciones. Al hacer una edición o agregar, quiero cambiar el nombre de un archivo cargado de forma dinámica en función de la identificación del contenido. Puedo hacer esto usando la función callback_after_upload grocery crud.

Quiero una próxima identificación del contenido mientras agrego un nuevo contenido. Traté de usar la función nextval() , pero la secuencia se incrementa con ella. ¿Cómo se puede obtener el último valor de la secuencia sin usar la función nextval() ?

¿O hay una manera simple de que pueda hacer esto?

RETURNING

En PostgreSQL moderno (8.2 o posterior), puede hacer esto con un solo viaje de ida y vuelta a la base de datos:

 INSERT INTO tbl(filename) VALUES ('my_filename') RETURNING tbl_id; 

tbl_id es una columna en serial . Más en el manual .

Obtener valor de manera explícita

Si el filename necesita incluir tbl_id (redundantemente), aún puede usar una sola consulta.
Utilice lastval() o el currval() más específico currval() :

 INSERT INTO tbl (filename) VALUES ('my_filename' || lastval()) -- or currval('tbl_tbl_id_seq') RETURNING tbl_id; 

El manual sobre lastval() :

Esta función es idéntica a currval , excepto que en lugar de tomar el nombre de la secuencia como argumento obtiene el valor de la última secuencia utilizada por nextval en la sesión actual.

Si tiene (o puede tener) múltiples secuencias vinculadas a la tabla (incluso a través de desencadenantes u otros efectos secundarios), la forma segura es usar currval('tbl_tbl_id_seq') .

Nombre de la secuencia

El literal de cadena 'tbl_tbl_id_seq' en mi ejemplo se supone que es el nombre real de la secuencia y se regclass a regclass , lo que genera una excepción si no se puede encontrar una secuencia de ese nombre en el actual search_path .

tbl_tbl_id_seq es el valor predeterminado generado automáticamente para una tabla tbl con una columna en serie tbl_id . Pero no hay garantías. Una columna predeterminada puede obtener valores de cualquier secuencia si así se define. Y si se toma el nombre predeterminado al crear la tabla, Postgres elige el siguiente nombre libre de acuerdo con un algoritmo codificado.

Si no conoce el nombre de la secuencia de una columna en serial , pg_get_serial_sequence() con la función dedicada pg_get_serial_sequence() . Incluso se puede hacer sobre la marcha:

 INSERT INTO tbl (filename) VALUES ('my_filename' || currval(pg_get_serial_sequence('tbl', 'tbl_id')) RETURNING tbl_id; 

SQL Fiddle.

El valor obtenido previamente de una secuencia se accede con la función currval() .

Pero eso solo devolverá un valor si se ha llamado a nextval() antes de eso.

No hay absolutamente ninguna forma de “leer” el siguiente valor de una secuencia sin obtenerla realmente.

Pero tu pregunta no está clara. Si llama a nextval() antes de hacer la inserción, puede usar ese valor en la inserción. O mejor aún, use currval() en su statement de inserción:

 select nextval('my_sequence') ... ... do some stuff with the obtained value insert into my_table(id, filename) values (currval('my_sequence'), 'some_valid_filename'); 

Incluso si esto se puede hacer de alguna manera, ¡es una idea terrible, ya que sería posible obtener una secuencia que luego sería utilizada por otro disco!

Una idea mucho mejor es guardar el registro y luego recuperar la secuencia después.

Si no estás en una sesión puedes simplemente nextval (‘you_sequence_name’) y está bien.

Para responder a su pregunta literalmente, a continuación se explica cómo obtener el siguiente valor de una secuencia sin boostla:

 SELECT CASE WHEN is_called THEN last_value + 1 ELSE last_value END FROM sequence_name 

Obviamente, no es una buena idea usar este código en la práctica. No hay garantía de que la próxima fila realmente tenga esta identificación. Sin embargo, para fines de depuración, puede ser interesante conocer el valor de una secuencia sin incrementarla, y así es como puede hacerlo.

Intenté esto y funciona perfectamente

 @Entity public class Shipwreck { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq") @Basic(optional = false) @SequenceGenerator(name = "seq", sequenceName = "shipwreck_seq", allocationSize = 1) Long id; 

….

 CREATE SEQUENCE public.shipwreck_seq INCREMENT 1 START 110 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1;