Est-il possible de supprimer toutes les contraintes NOT NULL d'une table en une fois?
J'ai une grande table avec beaucoup de contraintes NOT NULL et je cherche une solution plus rapide que de les supprimer séparément.
Vous pouvez tous les regrouper dans la même instruction alter:
alter table tbl alter col1 drop not null,
alter col2 drop not null,
…
Vous pouvez également extraire la liste des colonnes pertinentes du catalogue, si vous avez envie d'écrire un bloc do pour générer le SQL requis. Par exemple, quelque chose comme:
select a.attname
from pg_catalog.pg_attribute a
where attrelid = 'tbl'::regclass
and a.attnum > 0
and not a.attisdropped
and a.attnotnull;
(Notez que cela inclut également les champs liés à la clé primaire, vous devrez donc les filtrer.)
Si vous faites cela, n'oubliez pas d'utiliser quote_ident()
au cas où vous auriez besoin de traiter des caractères potentiellement étranges dans les noms de colonnes.
Si vous voulez supprimer toutes les contraintes NOT NULL
dans PostreSQL, vous pouvez utiliser cette fonction:
CREATE OR REPLACE FUNCTION dropNull(varchar) RETURNS integer AS $$
DECLARE
columnName varchar(50);
BEGIN
FOR columnName IN
select a.attname
from pg_catalog.pg_attribute a
where attrelid = $1::regclass
and a.attnum > 0
and not a.attisdropped
and a.attnotnull and a.attname not in(
SELECT
pg_attribute.attname
FROM pg_index, pg_class, pg_attribute
WHERE
pg_class.oid = $1::regclass AND
indrelid = pg_class.oid AND
pg_attribute.attrelid = pg_class.oid AND
pg_attribute.attnum = any(pg_index.indkey)
AND indisprimary)
LOOP
EXECUTE 'ALTER TABLE ' || $1 ||' ALTER COLUMN '||columnName||' DROP NOT NULL';
END LOOP;
RAISE NOTICE 'Done removing the NOT NULL Constraints for TABLE: %', $1;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
Veuillez noter que les clés primaires seront exclues.
Ensuite, vous pouvez l'appeler en utilisant:
SELECT dropNull (TABLENAME);
ALTER TABLE nom_table ALTER COLUMN [SET NOT NULL | DROP NOT NULL]
Il y a un chemin rapide et sale avec les privilèges superutilisateur:
UPDATE pg_attribute
SET attnotnull = FALSE
WHERE attrelid = 'tbl_b'::regclass -- schema-qualify if needed!
AND attnotnull
AND NOT attisdropped
AND attnum > 0;
Le raccourci est tentant. Mais si vous vous trompez, vous risquez de casser votre système.
La règle de base est la suivante: ne modifiez jamais directement les catalogues système.
La méthode clean nécessite uniquement des privilèges réguliers pour modifier la table: automatisez-la avec du SQL dynamique dans une instruction DO
(ceci implémente ce que Denis a déjà suggéré ):
DO
$$
BEGIN
EXECUTE (
SELECT 'ALTER TABLE tbl_b ALTER '
|| string_agg (quote_ident(attname), ' DROP NOT NULL, ALTER ')
|| ' DROP NOT NULL'
FROM pg_catalog.pg_attribute
WHERE attrelid = 'tbl_b'::regclass
AND attnotnull
AND NOT attisdropped
AND attnum > 0
);
END
$$
Toujours très vite. Exécuter care avec des commandes dynamiques et méfiez-vous de l'injection SQL.
Ceci est un dérivé de cette réponse plus grande:
Générer des valeurs DEFAULT dans un CTE UPSERT à l’aide de PostgreSQL 9.3
Il nous faut alors supprimer les contraintes NOT NULL d'une table créée avec:
CREATE TABLE tbl_b (LIKE tbl_a INCLUDING DEFAULTS);
Depuis, par documentation :
Les contraintes non nulles sont toujours copiées dans la nouvelle table.
J'ai eu un scénario nécessitant de supprimer le NOT NULL
de chaque champ avec un certain nom dans toute la base de données. Voici ma solution. La clause where
peut être modifiée pour gérer le modèle de recherche dont vous avez besoin.
DO $$ DECLARE row record;
BEGIN FOR row IN
(
SELECT
table_schema, table_name, column_name
FROM
information_schema.columns
WHERE
column_name IN ( 'field1', 'field2' )
)
LOOP
EXECUTE
'ALTER TABLE ' || row.table_schema || '.' || row.table_name || ' ALTER '
|| string_agg (quote_ident(row.column_name), ' DROP NOT NULL, ALTER ')
|| ' DROP NOT NULL;';
END LOOP;
END; $$;
emboîté quelques autres exemples, cela a fonctionné mieux pour mes besoins