一般的な操作は、存在しない場合は新しい行を挿入するか、既存の行を更新することです。残念ながら、SQL ステートメントの挿入と更新の構文は完全に異なります。挿入は列のリストに対応する値のリストを受け取りますが、更新は列=値のペアのリストを受け取ります。MySQL の "insert...on duplicate key update" ステートメント (その upsert ステートメント) は、完全な挿入列/値リストとそれに続く完全な更新列/値リストを必要とするため、この問題を解決しません。[更新: 以下の Wrikken からのコメントは、2 つのステートメントが column=value 構文を共有できることを指摘していますが、他の問題は残っています。]
この問題に関連して、トリガーを使用してデータをチェックする場合 (私のように)、2 つのトリガー (before-insert と before-update) が必要であり、"new" 修飾子を使用する必要があるため、トリガーごとに 1 回ずつ、チェック コードを 2 回記述するか、プロシージャに入れる必要があります。プロシージャを使用する場合は、各列を個別のパラメータとして渡す必要があります。これは、プロシージャが "new" を使用できないためです。これは、多数の列がある場合にエラーが発生しやすくなる可能性があるためです。各列は、create table ステートメントでそのタイプを持っている必要があり、次に、チェック手順の定義で 2 回目のタイプを持っている必要があります。少しのミスで、見つけにくい微妙なバグが作成されます。同じことを 2 回コーディングするアプローチは好きではありません。(これは非正規化に相当します。)
この挿入/更新の問題について考えて、私は次のアイデアをいじっています。特に誰かが実際に試した場合は、フィードバックをお願いします:
最小限のデータのみを保持するプレースホルダー行に対してのみ挿入を使用し、主キーを取得または設定します。次に、ユーザーが入力したすべてのデータを更新ステートメントに入れます。これで、単純な更新のように、「重複キーの更新時に挿入...」は必要ありません。また、挿入時にチェックするものがないため、更新前トリガーでのみデータをチェックする必要があります。(入力フォームからユーザーが提供したすべてのデータは、更新によって処理されますが、挿入によって処理されることはありません。)
もちろん、この方法の主な欠点は、新しい行に対して 2 つの操作があることです。つまり、挿入ではなく、挿入と更新です。ただし、次の理由により、それは要因ではない可能性があります。
挿入は比較的まれかもしれません。たとえば、私が数年前にリチャードソン (テキサス州) 学区のために行った生徒の採点アプリケーションでは、毎年数千人程度の生徒しか追加されませんでしたが、教師が学年を通しての制度です。
私が構築した他のいくつかのシステムでは、パフォーマンスは重要ではありませんでした。たとえば、私が取り組んでいる現在のシステムでは、週に数時間だけデータベースを更新する人が 2 人か 3 人しかいません。負荷が非常に小さいため、2 つの操作 (挿入 + 更新) によって発生するオーバーヘッドは、1 つの操作だけで十分な場合に取るに足らないものです。(これは新しい行専用です。覚えておいてください。)
では、実際にこれを試した人はいますか: 最小限のプレースホルダー行を作成するためだけに挿入し、すべてのユーザー提供データの更新に更新を使用しますか?