Cómo eliminar todas las restricciones NO NULAS de una tabla PostgreSQL de una sola vez


¿Es posible eliminar todas las restricciones NOT NULL de una tabla de una sola vez?

Tengo una gran tabla con muchas restricciones NO NULAS y estoy buscando una solución que sea más rápida que soltarlas por separado.

Author: Erwin Brandstetter, 2013-11-22

6 answers

Puedes agruparlos todos en la misma declaración alter:

alter table tbl alter col1 drop not null,
                alter col2 drop not null,
                …

También puede recuperar la lista de columnas relevantes del catálogo, si desea escribir un do block para generar el sql necesario. Por ejemplo, algo como:

select a.attname
  from pg_catalog.pg_attribute a
 where attrelid = 'tbl'::regclass
   and a.attnum > 0
   and not a.attisdropped
   and a.attnotnull;

(Tenga en cuenta que esto también incluirá los campos relacionados con la clave primaria, por lo que querrá filtrarlos.)

Si haces esto, no olvides usar quote_ident() en el caso de que alguna vez necesites lidiar con personajes potencialmente extraños en los nombres de las columnas.

 58
Author: Denis de Bernardy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-22 14:07:33

Si desea eliminar todas las restricciones NOT NULL en PostreSQL, puede usar esta función:

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;

Tenga en cuenta que las claves primarias serán excluidas.

Entonces puedes llamarlo usando:

SELECCIONE dropNull (TABLENAME);

 8
Author: Paulo Fidalgo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-02 10:55:26

ALTER TABLE table_name ALTER COLUMN [SET NOT NULL / DROP NOT NULL]

 6
Author: jameel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-23 12:16:33

Hay un camino rápido y sucio con privilegios de superusuario :

UPDATE pg_attribute
SET    attnotnull = FALSE
WHERE  attrelid = 'tbl_b'::regclass  -- schema-qualify if needed!
AND    attnotnull
AND    NOT attisdropped
AND    attnum > 0;

El atajo es tentador. Pero si arruinas esto puedes terminar rompiendo tu sistema.
La regla básica es: nunca manipule directamente los catálogos del sistema.

La forma limpia solo necesita privilegios regulares para alterar la tabla: automatícela con SQL dinámico en una instrucción DO (esto implementa lo que Denis ya sugirió):

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
$$

Todavía muy rápido. Ejecutar tenga cuidado con los comandos dinámicos y tenga cuidado con la inyección SQL.

Este es un spin-off de esta respuesta más grande:
Generar valores PREDETERMINADOS en un CTE UPSERT usando PostgreSQL 9.3

Allí tenemos la necesidad de soltar restricciones NOT NULL de una tabla creada con:

CREATE TABLE tbl_b (LIKE tbl_a INCLUDING DEFAULTS);

Desde entonces, por documentación :

Las restricciones Not-null siempre se copian en la nueva tabla.

 4
Author: Erwin Brandstetter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:12

Tuve un escenario que necesitaba eliminar el NOT NULL de cada campo con un cierto nombre en toda la base de datos. Aquí estaba mi solución. La cláusula where podría modificarse para manejar cualquier patrón de búsqueda que necesite.

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; $$;

A cuestas algunos otros ejemplos, esto funcionó mejor para mis necesidades

 0
Author: Gareth Pursehouse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-05 06:13:29

Sí, lo es. Yo tenía el mismo problema..

Para resolver, tuve que escribir un script C#. net que atravesaba toda la base de datos plSql y eliminaba todas las restricciones coincidentes..

Para obtener información específica sobre cómo eliminar restricciones individuales, siga el enlace. http://www.techonthenet.com/oracle/foreign_keys/drop.php

 -1
Author: Vipul Mishra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-22 13:53:02