質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
ORM

ORM(オブジェクト関係マッピング)はオブジェクト指向のシステムとリレーショナルデータベースの間でマッピングを行う技術です。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

Q&A

解決済

1回答

2332閲覧

【相談】ユニーク制約を貼っているテーブルにデータをInsertする前に、ユニーク制約のチェックをするか悩んでいます。

naokitakeshita

総合スコア1

ORM

ORM(オブジェクト関係マッピング)はオブジェクト指向のシステムとリレーショナルデータベースの間でマッピングを行う技術です。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

0グッド

1クリップ

投稿2020/08/21 06:40

編集2020/08/24 17:13

【相談】ユニーク制約を貼っているテーブルにデータをInsertする前に、ユニーク制約のチェックをするか悩んでいます。

ユニーク制約を貼っているテーブルにデータをInsertする前に、ユニーク制約のチェックをするか悩んでいます。
TypeORMというORMを使っているのですが、チェックをしなくてもInsert後に発生したExceptionを確認してユニーク制約でエラーが起こったことはわかります。なので、チェック処理はコストがもったいないので不要かと思うのですが、その場合、TypeORMがエラーログを出力するので、それは意図通りなのでエラーログを残したくないなと思っています。
皆さんは、どうされていますか??

パターン1:Exceptinで確認(TypeORMがエラーログを出力してしまう)

try { model.insert(entry); } catch (e) { if (e.code == "ER_DUP_ENTRY") { return res.status(409).end(); } return res.status(500).end(); }

パターン2:事前チェック(すり抜けて500レスポンスになる可能性あり)

try { if (model.exsits(...) ) { return res.status(409).end(); } model.insert(entry); } catch (e) { // if (e.code == "ER_DUP_ENTRY") { 消し忘れ(2020/08/25に気づいたのでコメント化) return res.status(500).end(); }

パターン3:両方

try { if (model.exsits(...) ) { return res.status(409).end(); } model.insert(entry); } catch (e) { if (e.code == "ER_DUP_ENTRY") { return res.status(409).end(); } return res.status(500).end(); }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/08/21 06:51

ユニーク制約に衝突するようなデータは、「どのような」状況で投げられうるものですか? ・タイミングが悪い場合などに、一般ユーザーの操作でも起きうる ・管理画面を複数開くなど、運営側の操作に対してしか生じない ・攻撃者がHTMLビューやJavaScriptを無視したような、不正なリクエストを投げた場合に限られる ・汎用的に作っている箇所なので、特定の呼び方は想定できない
naokitakeshita

2020/08/21 07:23 編集

・タイミングが悪い場合などに、一般ユーザーの操作でも起きうる です。 もう少し詳しく説明すると、チャット機能を作っていて、「ChatUser」と「ChatRoom」が多対多になっていまして、その中間テーブルChatRoomUser(UserがどのRoomに所属するか、ChatUser.idとChatRoom.idのユニーク制約付複合インデックスを設定)のInsertになります。 なので、ユーザーが重複してAPIをたたいた場合、すでに同じChatRoomUserがある場合があります。
guest

回答1

0

ベストアンサー

キー重複したら、更新するんでしょうから、そもそもupsertにすれば良いのでは?
upsert with return functionality
外してたらゴメンナサイ。

投稿2020/08/21 06:55

sazi

総合スコア25193

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

naokitakeshita

2020/08/21 07:16 編集

すいません、もう少し詳しく説明させていただきます。 今、チャット機能を作っていて、「ChatUser」と「ChatRoom」が多対多になっていまして、その中間テーブルChatRoomUser(UserがどのRoomに所属するか)のInsertになります。 なので、ユーザーが重複してAPIをたたいた場合、すでに同じChatRoomUserがある場合があります。 その場合は、何も処理をせずに409を返して終ろうと思っています。 ただ、その確認処理のためにSelectを実行するコストを惜しんでいます。
sazi

2020/08/21 07:30

コストを考えるならinsertしてエラーにする方ですよね。 となると質問の要旨としては、エラーログを残さない方法という事ですので、それを強調した方が良いと思います。
naokitakeshita

2020/08/21 10:59 編集

アドバイスありがとうございます。 まず、パターン1〜3でどの実装が一番自然なのかが知りたかったです。 そもそもパターン1はどうなの?という意見もあるかなと思いまして。 saziさんが実装されるときは、このあたりの考え方や方針みたいなのはありますでしょうか? ケースバイケースでしょうか?
sazi

2020/08/21 12:18

要件が一番としか言えません。 挙げられている選択肢は、要件に対してどれも不足があるものという事なので、新たに要件を満たすものを実装します。 ORMには詳しくありませんが、SQLのみで解決するなら、insertで条件を付けてキー重複しない場合のみinsertするという事は可能ですので。
sazi

2020/08/22 00:51

それでもどれか選べというなら、パターン2です。
naokitakeshita

2020/08/24 17:37

回答ありがとうございます。 今回はExceptionでユニーク制約のチェックをする方針(パターン1)で進める事にしました。 自分はパターン1で他の人が実装しているのを見たことがなかったので、何かおかしい部分があるのか懸念しましたが、改めて考えてみると自分がこれまで関わってきたプロジェクトは論理削除を使っているところが多かったので、そもそもユニーク制約自体貼れないという理由で、パターン2ばかり見てだったんだと思います。 今回は自分一人のプロジェクトですし、DBも物理削除ですのでコストを優先してパターン1にする事にしました。 ORMのログ出るよ問題は自分で解決方法を探して見ます。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問