Aquí hay una versión corta y dulce que usa la declaración "DO":
DO $$
BEGIN
BEGIN
ALTER TABLE <table_name> ADD COLUMN <column_name> <column_type>;
EXCEPTION
WHEN duplicate_column THEN RAISE NOTICE 'column <column_name> already exists in <table_name>.';
END;
END;
$$
No puede pasarlos como parámetros, deberá realizar una sustitución de variables en la cadena en el lado del cliente, pero esta es una consulta autónoma que solo emite un mensaje si la columna ya existe, agrega si no es así y continuará fallando en otros errores (como un tipo de datos no válido).
No recomiendo hacer CUALQUIERA de estos métodos si se trata de cadenas aleatorias que provienen de fuentes externas. Independientemente del método que utilice (cadenas dinámicas del lado de la hendidura o del lado del servidor ejecutadas como consultas), sería una receta para el desastre, ya que lo abre a los ataques de inyección SQL.
DO $$ BEGIN BEGIN CREATE INDEX type_idx ON table1 USING btree (type); EXCEPTION WHEN duplicate_table THEN RAISE NOTICE 'Index exists.'; END; END;$$;
el mismo enfoque enCREATE INDEX
;) Gracias por su respuesta,DO $$
falla. Intenté loDO $$;
que falla también, hasta que recién comencé el bloque con elDO $$DECLARE r record;
que se da un ejemplo en los documentos de postgres de desarrollo .END; $$
un error de sintaxis (Postgres 9.3), tuve que usarEND $$;
en su lugarEXCEPTION
) es un poco más general y puede emplearse para tareas que no tienenIF NOT EXISTS
sintaxis, por ejemploALTER TABLE ... ADD CONSTRAINT
.Con Postgres 9.6 esto se puede hacer usando la opción
if not exists
fuente
ADD CONSTRAINT IF NOT EXISTS
aún no existe .Llamada:
Devuelve
TRUE
en caso de éxito, de lo contrarioFALSE
(la columna ya existe).Provoca una excepción para una tabla o nombre de tipo no válido.
¿Por qué otra versión?
Esto podría hacerse con una
DO
declaración, pero lasDO
declaraciones no pueden devolver nada. Y si es para uso repetido, crearía una función.Utilizo los tipos de identificadores de objetos
regclass
yregtype
para_tbl
y_type
que a) evita la inyección de SQL yb) verifica la validez de ambos de forma inmediata (la forma más barata posible). El nombre de la columna_col
aún no se ha desinfectadoEXECUTE
conquote_ident()
. Más explicación en esta respuesta relacionada:format()
requiere Postgres 9.1+. Para versiones anteriores concatene manualmente:Puede calificar esquemáticamente el nombre de su tabla, pero no tiene que hacerlo.
Puede comillas dobles los identificadores en la llamada de función para preservar el caso de camello y las palabras reservadas (pero no debe usar nada de esto de todos modos).
Pregunto en
pg_catalog
lugar de lainformation_schema
. Explicación detallada:Los bloques que contienen una
EXCEPTION
cláusula como la respuesta actualmente aceptada son sustancialmente más lentos. Esto es generalmente más simple y rápido. La documentación:fuente
DO
declaración, una ligera modificación para aceptarDEFAULT
y esto funcionó perfectamente!La siguiente consulta de selección volverá
true/false
, utilizando laEXISTS()
función.y use la siguiente instrucción SQL dinámica para alterar su tabla
fuente
Para aquellos que usan Postgre 9.5+ (creo que la mayoría de ustedes lo hacen), existe una solución bastante simple y limpia
fuente
la siguiente función verificará la columna si existe, devolverá el mensaje apropiado; de lo contrario, agregará la columna a la tabla.
fuente
Esta es básicamente la solución de sola, pero solo se limpió un poco. Es lo suficientemente diferente como para no solo querer "mejorar" su solución (además, creo que es grosero).
La principal diferencia es que usa el formato EXECUTE. Lo que creo que es un poco más limpio, pero creo que significa que debes estar en PostgresSQL 9.1 o más reciente.
Esto ha sido probado en 9.1 y funciona. Nota: generará un error si el esquema / nombre_tabla / o tipo_datos no son válidos. Eso podría "arreglarse", pero podría ser el comportamiento correcto en muchos casos.
uso:
fuente
Se puede agregar a la función de invocación de scripts de migración y soltar cuando haya terminado.
fuente
En mi caso, por cómo se creó, es un poco difícil para nuestros scripts de migración atravesar diferentes esquemas.
Para evitar esto, usamos una excepción que simplemente captó e ignoró el error. Esto también tuvo el agradable efecto secundario de ser mucho más fácil de ver.
Sin embargo, tenga cuidado de que las otras soluciones tengan sus propias ventajas que probablemente superen a esta solución:
fuente
Puedes hacerlo de la siguiente manera.
Por lo tanto, soltará la columna si ya existe. Y luego agregue la columna a una tabla en particular.
fuente
Simplemente verifique si la consulta devolvió un column_name.
Si no, ejecute algo como esto:
Donde pones algo útil para 'x' e 'y' y, por supuesto, un tipo de datos adecuado donde utilicé int.
fuente