0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PostgreSQL - 1つのSQLでマスターに追加してテーブルで利用する

Posted at

前提のおはなし

  • テーブルAとテーブルBは両方にidがあります
  • テーブルBにはテーブルA_idフィールドで関連付けをしています
  • これらはFOREIGN KEYで外部キー制約をかけています

問題

  • この2つのテーブルに、新しい行を追加したいので、テーブルAに行を追加、その後テーブルBに行を追加する
  • これをなるべく1つのSQLで行いたい

SQLで解決策

WITH ins AS (
    INSERT INTO table_a (カラム1, カラム2, カラム3)
    VALUES (@カラム1, @カラム2, @カラム3)
    ON CONFLICT (カラム1) DO NOTHING
    RETURNING id
), selected_id AS (
    SELECT id FROM ins
    UNION ALL
    SELECT id FROM table_a WHERE カラム1 = @カラム1
    LIMIT 1
)
INSERT INTO table_b (table_a_id, カラムX, カラムY, カラムZ)
SELECT id, @カラムX, @カラムY, @カラムZ FROM selected_id
RETURNING id;
  • まず、Insertをかけてみます。CONFLICTで衝突した場合は値が返りません
  • 次のSELECTでCONFLICTの原因となった値で検索しています
  • その結果の一つを使って、テーブルに値を挿入しています

C#で実装

これを以下のように実装してみました。
個人的には「複数行の文字列を貼り付けただけ」のSQLはとても
気持ちが悪いのですが、今はわかりやすさ優先で記載しています。

実際のコーディング時には、文字列連結でやるか、StringBuilderでやるかと
思います

using System;
using System.Threading.Tasks;
using Npgsql;

class Program
{
    static async Task Main()
    {
        var connString = "Host=localhost;Username=postgres;Password=yourpassword;Database=yourdb";
        await using var conn = new NpgsqlConnection(connString);
        await conn.OpenAsync();

        var column1Value = "example";  // 実際の値に置き換え
        var column2Value = "data";
        var column3Value = "more data";
        var columnXValue = "valX";
        var columnYValue = "valY";
        var columnZValue = "valZ";

        var query = @"
            WITH ins AS (
                INSERT INTO table_a (カラム1, カラム2, カラム3)
                VALUES (@col1, @col2, @col3)
                ON CONFLICT (カラム1) DO NOTHING
                RETURNING id
            ), selected_id AS (
                SELECT id FROM ins
                UNION ALL
                SELECT id FROM table_a WHERE カラム1 = @col1
                LIMIT 1
            )
            INSERT INTO table_b (table_a_id, カラムX, カラムY, カラムZ)
            SELECT id, @colX, @colY, @colZ FROM selected_id
            RETURNING id;
        ";

        await using (var cmd = new NpgsqlCommand(query, conn))
        {
            cmd.Parameters.AddWithValue("col1", column1Value);
            cmd.Parameters.AddWithValue("col2", column2Value);
            cmd.Parameters.AddWithValue("col3", column3Value);
            cmd.Parameters.AddWithValue("colX", columnXValue);
            cmd.Parameters.AddWithValue("colY", columnYValue);
            cmd.Parameters.AddWithValue("colZ", columnZValue);

            var result = await cmd.ExecuteScalarAsync();
            if (result == null)
            {
                throw new Exception("テーブルBの挿入に失敗しました");
            }

            Console.WriteLine($"テーブルBに挿入したID: {result}");
        }
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?