PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Pourquoi ce code échoue dans PostgreSQL et comment y remédier (contournement) ? Est-ce un défaut du moteur SQL Postgres ?

... vous dit que votre spb_getWord() génère des valeurs qui existent déjà dans le SPB_WORD table. Vous devez mettre à jour la fonction pour vérifier si le mot existe déjà avant de quitter la fonction - si c'est le cas, régénérez jusqu'à ce qu'il en rencontre un qui n'existe pas.

Je pense que votre spb_runme() doit ressembler à :

create or replace function spb_runme() returns void as $$
DECLARE
  v_word VARCHAR(410);

begin
  perform setval('spb_wordnum_seq', 1, false);
  truncate table spb_word4obj, spb_word, spb_obj_word;

  for j in 0 .. 50000-1 loop

    if j % 100 = 0 then raise notice 'j = %', j; end if;

    for i in 0 .. 20 - 1 loop
      v_word := spb_getWord();
      INSERT INTO spb_word (word) VALUES (v_word);

      INSERT INTO spb_word4obj 
        (word, idx, doc_id, word_id)
        SELECT w.word, i, j, w.id
          FROM SPB_WORD w 
         WHERE w.word = v_word;

    end loop;

    INSERT INTO spb_obj_word (word_id, idx, doc_id) 
    SELECT w4o.word_id, w4o.idx, w4o.doc_id 
      FROM SPB_WORD4OBJ w4o 
     WHERE w40.doc_id = j;

  end loop;
end;

L'utilisation de cela vous permettrait de changer le word_id pour ne pas prendre en charge les valeurs NULL. Lorsque vous traitez avec des clés étrangères, remplissez le tableau auquel la clé étrangère fait référence en premier - commencer par le parent, puis s'attaquer à ses enfants.

L'autre changement que j'ai fait était de stocker le spb_getWord() dans une variable (v_word ), car appeler la fonction plusieurs fois signifie que vous obtiendrez une valeur différente à chaque fois.

Dernière chose - j'ai supprimé l'instruction de suppression. Vous avez déjà tronqué le tableau, il n'y a rien à supprimer. Certainement rien associé à une valeur de j .