ホームページ  >  記事  >  データベース  >  主キーまたは一意制約を使用しない DB 内の行を更新/挿入します

主キーまたは一意制約を使用しない DB 内の行を更新/挿入します

Linda Hamilton
Linda Hamiltonオリジナル
2024-10-19 10:52:29258ブラウズ

Upsert a row in a DB that doesn

プログラマーとしての 7 年間のキャリアの中で、私はほとんどの場合 ORM を介して SQL を操作してきました。私が特に便利だと思う Laravel の Eloquent ORM の機能の 1 つは、その updateOrInsert() メソッドです。

DB::table('posts')
    ->updateOrInsert(
        ['slug' => 'about'], // matching condition
        ['content' => 'Like and subscribe'] // created or updated values
    );

上記の例では、Eloquent は、posts テーブル内でスラッグが「about」に等しい行を探します。そのスラッグを含む行が存在する場合、Eloquent はその行のコンテンツを「いいね!」と「購読」に更新します。そのスラッグを含む行が存在しない場合、Eloquentは「about」のスラッグと「Like and subscribe」の内容を含む新しい行を作成します。

問題: 主キーまたは一意の制約がない

現在、古い WordPress サイトから新しい WordPress サイトにページ データを移動する移行スクリプトを作成しています。スクリプトは古いサイトのデータベースに接続し、新しいサイトのデータベースにインポートできる SQL ファイルを作成します。新しいサイトにはすでに手動で移動されたページがいくつかありますが、そのコンテンツは古くなっている可能性があります。新しいサイトにページがすでに存在する場合、それを再度作成するのではなく、すでに存在するページを更新したいと考えます。ページの URL スラッグに対応する WordPress データベースの post_name 列を使用して、ページが既に存在するかどうかを判断できます。

post_name が主キーの場合、REPLACE ステートメントを使用して Eloquent の createOrUpdate() メソッドと同様のことを実行できますが、post_name は主キーではありません。

post_name に一意の制約がある場合、INSERT ... ON DUPLICATE KEY UPDATE ステートメントを使用して Eloquent の createOrUpdate() メソッドと同様のことを実現できますが、post_name には一意の制約がありません。

ああ、WordPress の楽しさ。

MySQL の IF ステートメントを調べましたが、IF ステートメントはストアド プロシージャ、トリガー、関数でのみ機能します。新しいサイトのデータベースにインポートする SQL ファイルにストアド プロシージャを作成したくなかったので、他のオプションを探す必要がありました。

解決策: 2 つのステートメント

純粋な SQL で Eloquent の updateOrInsert() 機能をエミュレートするために私が見つけた最も簡単な解決策は、問題を 2 つの部分に分割することでした。

  1. 一致するスラッグを使用して既存の行を更新します。
  2. 一致するスラッグを持つ行がない場合は、新しい行を作成します。

実際の動作は次のとおりです:

-- Update the post if it already exists.

UPDATE wp_posts
SET post_type = 'page',
    post_title = 'About',
    post_content = 'Like and subscribe'
WHERE post_name = 'about';

-- Create a new post if it does not exist.

INSERT INTO wp_posts (post_name, post_type, post_title, post_content)
SELECT 'about', 'page', 'About', 'Like and subscribe'
WHERE NOT EXISTS (
    SELECT 1
    FROM wp_posts
    WHERE post_name = 'about'
);

注: この例では、簡潔さと明確さのために WordPress に必要な wp_posts 列の多くを省略しています。

INSERT ... SELECT ステートメントについて学んだとき、私にとっては「なるほど」と思った瞬間でした。別のテーブルからのクエリの結果を使用して、一度に多数の挿入を実行することを目的としています。ただし、独自の値を指定し、post_name が「about」の投稿が存在しない場合にのみ挿入を実行することで、SQL の機能を悪用することができます。

これは、この問題に対する最もエレガントで効率的な解決策でしょうか?おそらくそうではありません。ただし、WordPress サイトの 1 回限りの移行には十分であり、ストアド プロシージャやアプリケーション ロジックを必要とせずに行を更新または挿入できます。この投稿が、ORM を使用せずに強力なクエリを作成する際に役立つことを願っています。

以上が主キーまたは一意制約を使用しない DB 内の行を更新/挿入しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。