postgresql - tabla - secuencias sql ejemplos
currval aún no se ha definido en esta sesión, ¿cómo obtener secuencias multisesión? (5)
Mi objetivo es obtener un campo de clave principal insertado automáticamente cuando se inserta una nueva fila en la tabla.
¿Cómo obtener una secuencia de una sesión a otra en PostgreSQL?
doubleemploi@hanbei:/home/yves$ psql -d test
Mot de passe :
psql (8.4.13)
Saisissez « help » pour l''''aide.
test=> create sequence test001 start 10;
CREATE SEQUENCE
test=> select currval(''test001'');
ERREUR: la valeur courante (currval) de la séquence « test00 » n''''est pas encore définie dans cette session
--- current value not yet defined this session (???)
test=> select setval(''test001'', 10);
setval
--------
10
(1 ligne)
test=> select currval(''test00'');
currval
---------
10
(1 ligne)
test=> /q
test@hanbei:/home/yves$ psql -d test
Mot de passe :
psql (8.4.13)
Saisissez « help » pour l''''aide.
test=> select currval(''test001'');
ERREUR: la valeur courante (currval) de la séquence « test00 » n''''est pas encore définie dans cette session
Daré una respuesta práctica para este asunto. Mi servidor de base de datos es usado por mis programas y mi terminal psql; así que hay múltiples sesiones. Actualmente estoy en mi terminal psql:
fooserver=> select currval(''fusion_id_seq'');
ERROR: currval of sequence "fusion_id_seq" is not yet defined in this session
fooserver=> select nextval(''fusion_id_seq'');
nextval
---------
320032
(1 row)
fooserver=> select currval(''fusion_id_seq'');
currval
---------
320032
(1 row)
Parece que solo puedes ver los valores en tu propia sesión. Esto también afectará el currval de otra sesión. Probablemente esto esté relacionado con los subprocesos múltiples del servidor para aislar diferentes sesiones. El contador (serie en psql) es un objeto compartido. En mi opinión, esta sesión debería poder obtener el valor actual del contador siempre que el contador esté correctamente bloqueado para garantizar que solo un solo hilo (sesión) pueda incrementarlo (operación atómica). Pero podría estar equivocado aquí (no soy un experto en el servidor de bases de datos).
De hecho, nextval avanzará la secuencia y devolverá el nuevo valor, de modo que esa sería la respuesta para su pregunta.
currval devolverá el valor obtenido más recientemente con nextval para la secuencia especificada (aunque esto podría fallar si no se usó nextval en la sesión actual).
El currval
devolverá el último valor generado para la secuencia dentro de la sesión actual. Entonces, si otra sesión genera un nuevo valor para la secuencia, aún puede recuperar el último valor generado por SU sesión, evitando errores.
Pero, para obtener el último valor generado en cualquier sesión, puede usar lo anterior:
SELECT last_value FROM your_sequence_name;
Tenga cuidado, si el valor fue usado por otra sesión con una transacción no confirmada (o abortada) y usted usa este valor como referencia, puede obtener un error. Generalmente la gente solo necesita el currval
o incluso el retorno de setval
.
Este problema parece ser intermitente. Por coherencia, use CTE para obtener la secuencia insertada para la sesión actual.
CON insertado AS (INSERTAR EN notifn_main (notifn_dt, stat_id) SELECCIONE ahora (), 22 DESDE notifn RETURNING id) SELECCIONE la identificación desde insertada ENTO tmp_id;
Esto puede ser más simple de lo que piensas ...
Mi objetivo es obtener un campo de clave principal insertado automáticamente cuando se inserta una nueva fila en la tabla.
Solo establece el valor predeterminado de la columna:
ALTER TABLE tbl ALTER COLUMN tbl_id SET DEFAULT nextval(''my_seq''::regclass);
O aún más simple, cree la tabla con un tipo de serial
para la clave primaria para comenzar con:
CREATE TABLE tbl(
tbl_id serial PRIMARY KEY
,col1 txt
-- more columns
);
Crea una secuencia dedicada y establece el valor predeterminado para tbl_id automáticamente.
De esta manera, tbl_id
se asigna automáticamente el siguiente valor de la secuencia adjunta si no lo menciona en el INSERT
. Funciona con cualquier sesión, concurrente o no.
INSERT INTO tbl(col1) VALUES (''foo'');
Si quieres que el nuevo tbl_id
vuelva a hacer algo con él:
INSERT INTO tbl(col1) VALUES (''foo'') RETURNING tbl_id;