sql >> データベース >  >> RDS >> PostgreSQL

Postgresでデータを挿入して外部キーを設定する

    テーブルusers 主キーが必要です あなたが開示しなかったこと。この回答のために、users_idという名前を付けます。 。

    データ変更CTEを使用すると、これをかなりエレガントに解決できます。 PostgreSQLで導入9.1

    country ユニークです

    この場合、操作全体はかなり簡単です。

    WITH i AS (
        INSERT INTO addresses (country) 
        SELECT country
        FROM   users
        WHERE  address_id IS NULL 
        RETURNING id, country
        )
    UPDATE users u
    SET    address_id = i.id
    FROM   i
    WHERE  i.country = u.country;
    

    あなたはバージョン8.3に言及します あなたの質問で。アップグレード! Postgres8.3は寿命に達しました。

    とはいえ、これはバージョン8.3では十分に単純です。必要なステートメントは2つだけです:

    INSERT INTO addresses (country) 
    SELECT country
    FROM   users
    WHERE  address_id IS NULL;
    
    UPDATE users u
    SET    address_id = a.id
    FROM   addresses a
    WHERE  address_id IS NULL 
    AND    a.country = u.country;
    

    country ユニークではありません

    それはもっと難しいです。あなたはできた 1つのアドレスを作成し、それに複数回リンクするだけです。しかし、あなたはそのような便利な解決策を除外する1:1の関係について言及しました。

    WITH s AS (
        SELECT users_id, country
             , row_number() OVER (PARTITION BY country) AS rn
        FROM   users
        WHERE  address_id IS NULL 
        )
        , i AS (
        INSERT INTO addresses (country) 
        SELECT country
        FROM   s
        RETURNING id, country
        )
        , r AS (
        SELECT *
             , row_number() OVER (PARTITION BY country) AS rn
        FROM   i
        )
    UPDATE users u
    SET    address_id = r.id
    FROM   r
    JOIN   s USING (country, rn)    -- select exactly one id for every user
    WHERE  u.users_id = s.users_id
    AND    u.address_id IS NULL;
    

    正確に1つのidを明確に割り当てる方法はないため INSERTから返されます 同一のcountryを持つセット内のすべてのユーザーに 、ウィンドウ関数row_number()を使用します それらをユニークにするために。

    Postgres 8.3ではそれほど単純ではありません 。考えられる1つの方法:

    INSERT INTO addresses (country) 
    SELECT DISTINCT country -- pick just one per set of dupes
    FROM   users
    WHERE  address_id IS NULL;
    
    UPDATE users u
    SET    address_id = a.id
    FROM   addresses a
    WHERE  a.country = u.country
    AND    u.address_id IS NULL
    AND NOT EXISTS (
        SELECT * FROM addresses b
        WHERE  b.country = a.country
        AND    b.users_id < a.users_id
        ); -- effectively picking the smallest users_id per set of dupes
    

    これを繰り返す 最後のNULLまで 値がusers.address_idから削除されました 。




    1. Django + Psycopg2:InterfaceError:プロトコル3のみがサポートされています

    2. pipを使用してPythonMySQLdbモジュールをインストールするにはどうすればよいですか?

    3. データベースインデックスの数が多すぎますか?

    4. SQLiteでのTime()関数のしくみ