2017-01-31 5 views
0

私はPostgreSQLで、次の操作を実行しようとしています:FIXまたはPostgreSQLのFORループを使用しないよう

FOR realm_id IN (SELECT id from decision_realms WHERE id NOT IN (SELECT realm_id FROM voters WHERE realm_id IS NOT NULL)) 
LOOP 
    INSERT INTO voters (voter_user_id, max_weight, actual_weight) 
    SELECT contributor_user_id, pps, pps 
    FROM contributors WHERE 
     project_id= (SELECT project_id FROM goals WHERE id=(SELECT goal_id FROM decision_realms WHERE id=realm_id)) 
END LOOP; 

彼らはすべての作業indepedently、これは次のようになります。

(SELECT id from decision_realms WHERE id NOT IN (SELECT realm_id FROM voters WHERE realm_id IS NOT NULL)) 

は、単一の列を返します。 idおよび

INSERT INTO voters (voter_user_id, max_weight, actual_weight) 
SELECT contributor_user_id, pps, pps 
FROM contributors WHERE 
    project_id= (SELECT project_id FROM goals WHERE id=(SELECT goal_id FROM decision_realms WHERE id=1)) 

は、realm_idが値(1)にハードコードされている場合に、期待どおりに行をvotersテーブルに埋め込みます。

しかし、値1を変数に置き換えようとすると、selectの結果に基づいてループします。forループは機能しません。それは構文エラーがあると言います。

これはFOR LOOPを使用せずに行うことができますか?どのように書くべきですか?

答えて

1

エレガントないとテストしていません(それがエラーを有していてもよい)が、

with dec_realms as 
(
     SELECT contributor_user_id, pps, pps 
     FROM contributors WHERE 
      project_id in (
       SELECT project_id FROM goals WHERE id in (SELECT goal_id FROM decision_realms 
        WHERE id in (SELECT id from decision_realms WHERE id NOT IN (SELECT realm_id FROM voters WHERE realm_id IS NOT NULL)) 
        )) 
) 

INSERT INTO voters (voter_user_id, max_weight, actual_weight) 
    SELECT contributor_user_id, pps, pps 
    from dec_realms; 

その他のオプションは、その

のような制御構造 FORを使用することである

INSERT INTO voters (voter_user_id, max_weight, actual_weight) 
SELECT contributor_user_id, pps, pps 
from 
(
    SELECT contributor_user_id, pps, pps 
    FROM contributors WHERE 
     project_id in (
      (SELECT project_id FROM goals WHERE id in (SELECT goal_id FROM decision_realms 
       WHERE id in (SELECT id from decision_realms WHERE id NOT IN (SELECT realm_id FROM voters WHERE realm_id IS NOT NULL)) 
       )) 
)dec_realms 

または使用with文のようでなければなりません

DO 
$$ 
DECLARE 
    _id integer; 
BEGIN 
    FOR _id IN (SELECT id from decision_realms WHERE id NOT IN (SELECT realm_id FROM voters WHERE realm_id IS NOT NULL)) 
    LOOP 
     INSERT INTO voters (voter_user_id, max_weight, actual_weight) 
     SELECT contributor_user_id, pps, pps 
     FROM contributors WHERE 
      project_id= (SELECT project_id FROM goals WHERE id=(SELECT goal_id FROM decision_realms WHERE id=_id)); 
    END LOOP; 
END 
$$ 

Im soryエラーが発生した場合は、タブがありませんル構造。第1オプションと第2オプションは、各インサートを別々に実行するのではなく、1つの操作より速いでしょう。

1

構文エラーは表示されませんが、問合せで使用する列と同じ名前のPL/pgSQL変数があることが問題であると推測します。

具体的には、ループ変数はrealm_idであり、これも表votersの列の名前です。

解決策は、変数に異なる名前を使用することです。

+0

感謝@Laurenz、それは意味があります。残念ながら、私は変更しましたが、同じエラーを抱えています。 –

+0

私はスクリプトを に更新しました。DO $$ DECLARE rid BIGINT; BEGIN \t ALTER TABLE voters ALTER COLUMN id DROP NOT NULL; ID NOT IN decision_realmsから \t \t SELECT ID(realm_idがNULLではない有権者FROM realm_id SELECT) \t LOOP \t \t有権者(voter_user_id、max_weight、actual_weight) \t \t SELECT contributor_user_id、INTOインサート内のRID FOR \t \t \t \t PROJECT_ID =(ID =は、(WHERE ID = RID decision_realms FROM goal_idを選択目標FROM PROJECT_IDの選択))コントリビュータFROM PPS、PPS \t \t。 \t END LOOP; 終了 $$ 今は動作します...私はPSQLスクリプトとSQL文を混同しているようです... –

+0

私の提案された答えを見てください。私はまだそれがなぜ働いたのか分からない。私は大きな移行.pgsファイルを持っており、これまでDO $$もBEGINも使用していません –

0

これは機能しています。おそらく、それはスクリプトでなければならず、声明だけでなく、そのようなものでなければなりません。

DO 
$$ 
DECLARE rid BIGINT; 
BEGIN 
    ALTER TABLE voters ALTER COLUMN id DROP NOT NULL; 

    FOR rid IN 
     SELECT id from decision_realms WHERE id NOT IN (SELECT realm_id FROM voters WHERE realm_id IS NOT NULL) 
    LOOP 
     INSERT INTO voters (voter_user_id, max_weight, actual_weight) 
     SELECT contributor_user_id, pps, pps 
     FROM contributors WHERE 
     project_id= (SELECT project_id FROM goals WHERE id=(SELECT goal_id FROM decision_realms WHERE id=rid)); 
    END LOOP; 

END 
$$ 
関連する問題