Creating databases and tables using the postgresql module in Ansible is pretty straight forward and works great, but I canĀ“t really figure out how to create a foreign key constraint.
Eg. I create a table in Ansible like this:
- name: "Create foo table"
become: yes
become_user: postgres
community.postgresql.postgresql_table:
db: test_db
owner: postgres
name: foo
columns:
- id bigserial PRIMARY KEY NOT NULL
- bar_id bigint
Now I would like to create a foreign key constraint that references the id column in the table bar. In Postgresql I could add a foreign key constrain this like this:
ALTER TABLE foo ADD CONSTRAINT bar_id_fkey FOREIGN KEY (bar_id) REFERENCES bar (id) MATCH FULL;
How can this be done in Ansible?
You can create a foreign key constraint when you create the table by adding a CONSTRAINT to the columns list, like this:
- name: "Create foo table"
become: yes
become_user: postgres
community.postgresql.postgresql_table:
db: test_db
owner: postgres
name: foo
columns:
- id bigserial PRIMARY KEY NOT NULL
- bar_id bigint
- CONSTRAINT bar_id_fkey FOREIGN KEY (bar_id) REFERENCES bar (id) MATCH FULL;
Or just include the constraint in the column definition:
- name: "Create foo table"
become: yes
become_user: postgres
community.postgresql.postgresql_table:
db: test_db
owner: postgres
name: foo
columns:
- id bigserial PRIMARY KEY NOT NULL
- bar_id bigint REFERENCES bar(id) MATCH FULL
But you cannot add a constraint after the fact using the
postgresql_table module: it doesn't support the use of ALTER TABLE
to synchronize the database table with changes in your playbook.
From the documentation, the postgresql_table module can be used to
"change some table attributes", but looking at the source that appears
to be limited to:
Renaming the table
Changing the table owner
Changing the tablespace
Changing store parameters
Related
I have a database schema that looks something like this:
- Table: User
- Column: id, primary key
- Table: UserAlias
- Column: userId, foreign key
- Column: isPrimary, boolean
I want to make it so that users have to have a primary alias, but cannot make a secondary one until they already have a primary one.
Is it possible to structure a constraint like this? Maybe a recursive foreign key constraint can work? Thanks!
I have a table in Postgres with a composite primary key.
What's the syntax to alter another existing table to add a composite foreign key to the composite primary key of the first table?
ALTER TABLE my_fk_table
ADD CONSTRAINT my_fk
FOREIGN KEY (pk1, pk2)
REFERENCES my_pk_table
ON DELETE CASCADE;
I'm making a DB in PostgreSQL and I need a little help.
The user control work with LDAP, and I have a table called modules where I put all the information about the system modules,
Then I created a table called user_module where I put the username and the integer that references a module (in modules table), in this table, you can add/drop rows and I guess I don't need a primary Key for that or isn't it?
I'm using PgAdmin III and it said "I only can View data in this table, I need create a Primary for editing"
Table Code
CREATE TABLE public.adm_mod_usu
(
cusuario text NOT NULL,
cmodulo_det integer NOT NULL,
CONSTRAINT fk_adm_mod_usu_cmodulo_det FOREIGN KEY (cmodulo_det)
REFERENCES public.adm_mod_det (cmodulo_det) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE RESTRICT,
CONSTRAINT fk_adm_mod_usu_unique_cpermiso UNIQUE (cusuario, cpermiso)
USING INDEX TABLESPACE sistema_index
)
WITH (
OIDS=FALSE
);
ALTER TABLE public.adm_mod_usu
OWNER TO postgres;
GRANT ALL ON TABLE public.adm_mod_usu TO public;
GRANT ALL ON TABLE public.adm_mod_usu TO postgres;
By the help from a_horse_with_no_name:
ALTER TABLE public.adm_mod_usu DROP CONSTRAINT fk_adm_mod_usu_unique_cpermiso;
ALTER TABLE public.adm_mod_usu
ADD CONSTRAINT fk_adm_mod_usu PRIMARY KEY (cusuario, cpermiso)
USING INDEX TABLESPACE sistema_index;
I change the unique constraint to primary.
I'm using PostgreSQL. I'm trying to create a primary key column taht is a UUID, so I ran this statement
ALTER TABLE my_object_times ADD PRIMARY KEY (id) DEFAULT uuid_generate_v4();
but I get the error
PG::SyntaxError: ERROR: syntax error at or near "DEFAULT"
What is the proper way to write the above statement (I'm doing alter because I'm changing an existing primary key column)?
If the column id already exists in the table and you want to modify it by making it the primary key and adding a default value, you can do it in 2 steps:
ALTER TABLE my_object_times ADD PRIMARY KEY (id);
ALTER TABLE my_object_times ALTER COLUMN id SET DEFAULT uuid_generate_v4();
If the column doesn't exist at all, then you can create it with all the attributes you want, by simply doing:
ALTER TABLE my_object_times ADD id uuid PRIMARY KEY DEFAULT uuid_generate_v4();
(I cannot test this right now but it should work)
In order to use uuid_generate_v4(), you first need to execute:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
How can I alter the reference to a table in PostgreSQL when the table name has been changed?
Say I have:
CREATE TABLE example1 (
id serial NOT NULL PRIMARY KEY,
name varchar(100)
);
CREATE TABLE example2 (
id serial NOT NULL PRIMARY KEY,
example1fk integer REFERENCES example1 (id) DEFERRABLE INITIALLY DEFERRED
);
Later I do:
ALTER TABLE example1 RENAME TO example3;
How to change the definition of the foreign key constraint?
example1fk integer REFERENCES example1 (id) DEFERRABLE INITIALLY DEFERRED,
Internal dependencies between tables and / or other objects are never bound to the object name. Internally, every object is stored in a catalog table and the OID (internal primary key) of the object is used for everything else.
Accordingly, a FOREIGN KEY reference is stored in the catalog tables pg_constraint (the constraint itself incl. its name) and pg_depend. Changing table names will not impair functionality at all.
The name of the constraint remains unchanged. You can ignore that, or you may want to rename the constraint so it's not misleading.
However, since you did not specify a constraint name at creation time, the system picked a default, which is example2_example1fk_fkey in your case unless the name was taken. No reference to the referenced table name. But the column name will likely have to change in your example, too. And that is used in the constraint name.
ALTER TABLE example2 RENAME example1fk TO example3fk; -- rename column
In Postgres 9.2 or later you can just rename the constraint as well (as dequis commented):
ALTER TABLE example2 RENAME CONSTRAINT example2_example1fk_fkey TO example2_example3fk_fkey;
In older versions, you have to drop and recreate the constraint to rename it, best in a single statement:
ALTER TABLE example2 -- rename constraint
DROP CONSTRAINT example2_example1fk_fkey
, ADD CONSTRAINT example2_example3fk_fkey FOREIGN KEY (example3fk)
REFERENCES example3 (id) DEFERRABLE INITIALLY DEFERRED;
Details in the manual.