web-dev-qa-db-fra.com

Modifier le jeu de colonnes non nul échoue

Considérez le tableau suivant avec environ 10 millions de lignes

CREATE TABLE user
(
  id bigint NOT NULL,
  ...
  CONSTRAINT user_pk PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
)

Ensuite, j'ai appliqué l'alter suivant

ALTER TABLE USER ADD COLUMN BUSINESS_ID    VARCHAR2(50);
--OK
UPDATE USER SET BUSINESS_ID = ID; //~1500 sec
--OK
ALTER TABLE USER ALTER COLUMN BUSINESS_ID SET NOT NULL;

    ERROR: column "business_id" contains null values
    SQL state: 23502

C'est très étrange car la colonne id (qui a été copiée dans la colonne business_id) ne peut pas contenir de valeurs nulles car c'est la clé primaire, mais pour être sûr de la vérifier

select count(*) from USER where BUSINESS_ID is null
    --0 records

Je soupçonne que c'est un bug, je me demande juste si je manque quelque chose de trivial

21
dimcookies

La seule explication logique serait un simultané INSERT ..
(Utilisation de tbl au lieu du mot réservé user comme nom de table.)

ALTER TABLE tbl ADD COLUMN BUSINESS_ID    VARCHAR2(50);
--OK
UPDATE tbl SET BUSINESS_ID = ID; //~1500 sec
--OK

 HERE

ALTER TABLE tbl ALTER COLUMN BUSINESS_ID SET NOT NULL;

Pour éviter cela, utilisez plutôt:

ALTER TABLE tbl
ADD COLUMN BUSINESS_ID VARCHAR(50) DEFAULT ''; -- or whatever is appropriate
...

Ensuite, vous pouvez vous retrouver avec une valeur par défaut dans certaines lignes. Vous voudrez peut-être vérifier.

Ou exécutez tout comme bloc de transaction et prenez un verrou exclusif pour être sûr:

BEGIN;
LOCK tbl;
ALTER ...
UPDATE ...
ALTER ...
COMMIT;
18
Erwin Brandstetter

Peut-être qu'il veut une valeur par défaut? Documents Postgresql sur ALTER :

Pour ajouter une colonne, utilisez une commande comme celle-ci:

ALTER TABLE products ADD COLUMN description text;

La nouvelle colonne est initialement remplie avec la valeur par défaut donnée ( null si vous ne spécifiez pas de clause DEFAULT ).

Alors,

ALTER TABLE USER ALTER COLUMN BUSINESS_ID SET DEFAULT="", 
                 ALTER COLUMN BUSINESS_ID SET NOT NULL;
9
Ondra Žižka

Vous ne pouvez pas faire cela lors de la même transaction. Ajoutez votre colonne et mettez-la à jour. Ensuite, dans une transaction distincte, définissez la contrainte non nulle.

0
K.z