sql - tablas - Cómo crear una secuencia si no existe.
select sequence sql server (6)
Postgres 9.5+
IF NOT EXISTS
fue agregado para CREATE SEQUENCE
en Postgres 9.5. Esa es la solución simple ahora:
CREATE SEQUENCE IF NOT EXISTS myschema.myseq;
Pero considere los detalles de la respuesta obsoleta de todos modos ...
Y sabes sobre columnas serial
, ¿verdad?
Postgres 9.4 o mayor
El nombre de una secuencia entra en conflicto con nombres de objetos de varios tipos, no solo con secuencias. El manual:
El nombre de la secuencia debe ser distinto del nombre de cualquier otra secuencia, tabla, índice, vista o tabla externa en el mismo esquema.
Énfasis en negrita el mio
Así que tienes tres casos:
- El nombre no existe. -> Crear secuencia.
- Existe secuencia con el mismo nombre. -> ¿No hacer nada? Cualquier salida? Cualquier registro?
- Existe otro objeto conflictivo con el mismo nombre. -> hacer algo? Cualquier salida? Cualquier registro?
Debe especificar qué desea hacer en cualquiera de estos casos. La instrucción DO
podría verse así:
DO
$do$
DECLARE
_kind "char";
BEGIN
SELECT relkind
FROM pg_class
WHERE oid = ''myschema.myseq''::regclass -- sequence name, optionally schema-qualified
INTO _kind;
IF NOT FOUND THEN -- name is free
CREATE SEQUENCE myschema.myseq;
ELSIF _kind = ''S'' THEN -- sequence exists
-- do nothing?
ELSE -- object name exists for different kind
-- do something!
END IF;
END
$do$;
Tipos de objetos ( relkind
) en pg_class
acuerdo con el manual :
r = tabla ordinaria
i = índice
S = secuencia
v = vista
m = vista materializada
c = tipo compuesto
t = tabla de tostar
f = mesa extranjera
Relacionado:
Intenté usar el código de Check si la secuencia existe en Postgres (plpgsql) .
Para crear secuencia si no existe. Ejecutar este código dos veces provoca una excepción:
secuencia ... ya existe.
¿Cómo crear una secuencia solo si no existe?
Si la secuencia no existe, no se debe escribir ningún mensaje y no debe producirse ningún error, por lo que no puedo usar el procedimiento almacenado en la otra respuesta a esta pregunta, ya que escribe el mensaje en el archivo de registro cada vez que exista una secuencia.
do $$
begin
SET search_path = '''';
IF not EXISTS (SELECT * FROM pg_class
WHERE relkind = ''S''
AND oid::regclass::text = ''firma1.'' || quote_ident(''myseq''))
THEN
SET search_path = firma1,public;
create sequence myseq;
END IF;
SET search_path = firma1,public;
end$$;
select nextval(''myseq'')::int as nr;
Fui por una ruta diferente: solo coge la excepción:
DO
$$
BEGIN
CREATE SEQUENCE myseq;
EXCEPTION WHEN duplicate_table THEN
-- do nothing, it''s already there
END
$$ LANGUAGE plpgsql;
Una buena ventaja de esto es que no necesita preocuparse por cuál es su esquema actual.
La información sobre las secuencias se puede recuperar de la information_schema.sequences
( reference )
Intenta algo como esto (no probado):
...
IF not EXISTS (SELECT * FROM information_schema.sequences
WHERE sequence_schema = ''firma1'' AND sequence_name = ''myseq'') THEN
...
Postgres no tiene CREATE SEQUENCE IF NOT EXISTS
y si la tabla tiene un valor predeterminado usando la secuencia, si simplemente abandona la secuencia, podría obtener un error:
ERROR: no se puede descartar secuencia (nombre de secuencia) porque otros objetos dependen del estado de SQL: 2BP01
Para mí, este puede ayudar:
ALTER TABLE <tablename> ALTER COLUMN id DROP DEFAULT;
DROP SEQUENCE IF EXISTS <sequence_name>;
CREATE sequence <sequence_name>;
Si no necesita conservar la secuencia potencialmente existente, simplemente puede soltarla y luego volver a crearla:
DROP SEQUENCE IF EXISTS id_seq;
CREATE SEQUENCE id_seq;
Tengo una función para limpiar todas las tablas en mi aplicación de base de datos en cualquier momento. Se construye dinámicamente, pero la esencia es que elimina todos los datos de cada tabla y restablece la secuencia. Este es el código para restablecer la secuencia de una de las tablas:
perform relname from pg_statio_all_sequences where relname = ''privileges_id_seq'';
if found then
select setval (''privileges_id_seq'',1, false) into i_result;
end if;
Espero que esto ayude,
Loek
Estoy usando postgres 8.4, veo que usas 9.2. Podría marcar la diferencia donde se almacena la información.