Respuestas:
Esta característica se ha implementado en Postgres 9.1 :
CREATE TABLE IF NOT EXISTS myschema.mytable (i integer);
Para versiones anteriores , aquí hay una función para solucionarlo:
CREATE OR REPLACE FUNCTION create_mytable ()
RETURNS void AS
$func$
BEGIN
IF EXISTS (SELECT FROM pg_catalog.pg_tables
WHERE schemaname = 'myschema'
AND tablename = 'mytable') THEN
RAISE NOTICE 'Table myschema.mytable already exists.';
ELSE
CREATE TABLE myschema.mytable (i integer);
END IF;
END
$func$ LANGUAGE plpgsql;
Llamada:
SELECT create_mytable(); -- call as many times as you want.
Notas:
Las columnas schemaname
y tablename
en pg_tables
distinguen entre mayúsculas y minúsculas. Si cita entre comillas los identificadores en la CREATE TABLE
declaración, debe usar exactamente la misma ortografía. Si no lo hace, debe usar cadenas en minúsculas. Ver:
pg_tables
solo contiene tablas reales . El identificador aún puede estar ocupado por objetos relacionados. Ver:
Si el rol que ejecuta esta función no tiene los privilegios necesarios para crear la tabla, es posible que desee utilizarla SECURITY DEFINER
para que la función sea propiedad de otro rol con los privilegios necesarios. Esta versión es lo suficientemente segura.
CREATE FUNCTION
única vez. Es SELECT create_mytable();
posible que desee llamar muchas veces.
Prueba esto:
CREATE TABLE IF NOT EXISTS app_user (
username varchar(45) NOT NULL,
password varchar(450) NOT NULL,
enabled integer NOT NULL DEFAULT '1',
PRIMARY KEY (username)
)
IF NOT EXISTS
opción.
Creé una solución genérica a partir de las respuestas existentes que se pueden reutilizar para cualquier tabla:
CREATE OR REPLACE FUNCTION create_if_not_exists (table_name text, create_stmt text)
RETURNS text AS
$_$
BEGIN
IF EXISTS (
SELECT *
FROM pg_catalog.pg_tables
WHERE tablename = table_name
) THEN
RETURN 'TABLE ' || '''' || table_name || '''' || ' ALREADY EXISTS';
ELSE
EXECUTE create_stmt;
RETURN 'CREATED';
END IF;
END;
$_$ LANGUAGE plpgsql;
Uso:
select create_if_not_exists('my_table', 'CREATE TABLE my_table (id integer NOT NULL);');
Se podría simplificar aún más si se toma un solo parámetro si se extrae el nombre de la tabla del parámetro de consulta. También omití los esquemas.
Esta solución es algo similar a la respuesta de Erwin Brandstetter, pero usa solo el lenguaje sql.
No todas las instalaciones de PostgreSQL tienen el lenguaje plpqsql por defecto, esto significa que puede que tenga que llamar CREATE LANGUAGE plpgsql
antes de crear la función, y luego tener que eliminar el idioma nuevamente, para dejar la base de datos en el mismo estado que tenía antes (pero solo si la base de datos no tenía el lenguaje plpgsql para empezar). ¿Ves cómo crece la complejidad?
Agregar el plpgsql puede no ser un problema si está ejecutando su script localmente, sin embargo, si el script se usa para configurar el esquema en un cliente, puede no ser conveniente dejar cambios como este en la base de datos de clientes.
Esta solución está inspirada en una publicación de Andreas Scherbaum .
-- Function which creates table
CREATE OR REPLACE FUNCTION create_table () RETURNS TEXT AS $$
CREATE TABLE table_name (
i int
);
SELECT 'extended_recycle_bin created'::TEXT;
$$
LANGUAGE 'sql';
-- Test if table exists, and if not create it
SELECT CASE WHEN (SELECT true::BOOLEAN
FROM pg_catalog.pg_tables
WHERE schemaname = 'public'
AND tablename = 'table_name'
) THEN (SELECT 'success'::TEXT)
ELSE (SELECT create_table())
END;
-- Drop function
DROP FUNCTION create_table();
No existe CREAR TABLA SI NO EXISTE ... pero puede escribir un procedimiento simple para eso, algo como:
CREATE OR REPLACE FUNCTION prc_create_sch_foo_table() RETURNS VOID AS $$
BEGIN
EXECUTE 'CREATE TABLE /* IF NOT EXISTS add for PostgreSQL 9.1+ */ sch.foo (
id serial NOT NULL,
demo_column varchar NOT NULL,
demo_column2 varchar NOT NULL,
CONSTRAINT pk_sch_foo PRIMARY KEY (id));
CREATE INDEX /* IF NOT EXISTS add for PostgreSQL 9.5+ */ idx_sch_foo_demo_column ON sch.foo(demo_column);
CREATE INDEX /* IF NOT EXISTS add for PostgreSQL 9.5+ */ idx_sch_foo_demo_column2 ON sch.foo(demo_column2);'
WHERE NOT EXISTS(SELECT * FROM information_schema.tables
WHERE table_schema = 'sch'
AND table_name = 'foo');
EXCEPTION WHEN null_value_not_allowed THEN
WHEN duplicate_table THEN
WHEN others THEN RAISE EXCEPTION '% %', SQLSTATE, SQLERRM;
END; $$ LANGUAGE plpgsql;
No existe CREAR TABLA SI NO EXISTE ... pero puede escribir un procedimiento simple para eso, algo como:
CREATE OR REPLACE FUNCTION execute(TEXT) RETURNS VOID AS $$
BEGIN
EXECUTE $1;
END; $$ LANGUAGE plpgsql;
SELECT
execute($$
CREATE TABLE sch.foo
(
i integer
)
$$)
WHERE
NOT exists
(
SELECT *
FROM information_schema.tables
WHERE table_name = 'foo'
AND table_schema = 'sch'
);