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

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

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

INSERTとは、行を追加する、コンピュータのデータベース言語SQLにおけるデータ操作言語(DML)ステートメントの1つである

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

XAMPP

XAMPP(ザンプ)は、ウェブアプリケーションの実行に必要なフリーソフトウェアをパッケージングしたApacheディストリビューションです。 XAMPPひとつインストールするだけで、Apache、MySQL、PHP、Perlなどのソフトウェアと、 phpMyAdminなどの管理ツール、SQLiteなどのソフトウェアやライブラリモジュールなどを利用することが可能です。

Q&A

解決済

2回答

755閲覧

XAMPPを用いてブラウザからデータ登録 エラーを解消したいです。

mememe0331

総合スコア55

INSERT

INSERTとは、行を追加する、コンピュータのデータベース言語SQLにおけるデータ操作言語(DML)ステートメントの1つである

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

XAMPP

XAMPP(ザンプ)は、ウェブアプリケーションの実行に必要なフリーソフトウェアをパッケージングしたApacheディストリビューションです。 XAMPPひとつインストールするだけで、Apache、MySQL、PHP、Perlなどのソフトウェアと、 phpMyAdminなどの管理ツール、SQLiteなどのソフトウェアやライブラリモジュールなどを利用することが可能です。

0グッド

1クリップ

投稿2022/07/31 01:46

編集2022/07/31 02:42

前提

XAMPPを使用して、ブラウザからデータの登録を行いたいです。
しかし、重複したpid(ID)を登録する際にエラーが表示されてしまい、困っています。

実現したいこと

写真のようなデータをベースを作成して、XAMPPを用いて、ブラウザからデータの登録を行っています。
イメージ説明

pid(ID)を主キーで設定しただけでは、重複したpid(ID)を登録する際に、

Uncaught mysqli_sql_exception: Duplicate entry 'a123' for key 'PRIMARY'

というエラーが表示されます。

このエラーを表示させずに、別ブラウザで「このIDは既に使用されています」のように表示させたいです。

発生している問題・エラーメッセージ

同じpid(ID)のデータを登録しようとした際に、登録できないクエリを使用すれば、エラーは発生しないと考えて、以下のクエリを考えたのですが、

$query = "INSERT INTO products VALUES ('{$pid}', '{$name}', '{$cost}', '{$price}') WHERE NOT EXISTS (SELECT pid, name, cost ,price FROM products WHERE pid = '{$pid}')";

操作を行ったところ、

Uncaught mysqli_sql_exception: SQL 構文にエラーがあります。

とエラーが表示されます。
SQL文のどこが構文エラーになっているのでしょうか?

何かわかる方がいらっしゃりましたら、教えて頂きたいです。

試したこと

NOT EXISTSの使い方 で検索
INSERT 重複無し で検索

補足情報(FW/ツールのバージョンなど)

Windows10、XAMPP

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2022/07/31 01:59 編集

> 同じIDのデータを登録しようとした際に、登録できないようにしたいです。 何故 ID を主キーにするとか、ユニーク制約をつけるとかしないのですか?
mememe0331

2022/07/31 02:02

コメントありがとうございます。 IDを主キーにしていますが、もう一度同じIDを登録する際に、致命的なエラーでブラウザが止まってしまうことを避けたくて、今の質問に至っています。
退会済みユーザー

退会済みユーザー

2022/07/31 02:23 編集

> IDを主キーにしています であれば、質問に書いてあるあなたのやりたいこと「同じIDのデータを登録しようとした際に、登録できないようにしたい」はできていることになります。 上に書いた「致命的なエラーでブラウザが止まってしまうことを避けたく」という話は今初めて聞きました。さらに、話は MySQL にとどまらず、MySQL に INSERT する Web アプリも絡んでいると想像してますが、違いますか? 情報の後出し小出しはこういう Q&A サイトでは NG です。質問は編集できるので見直してください。
m.ts10806

2022/07/31 02:29

タイトルと質問内容がずれていること(もしくは主語が違う、大きさの問題もあり)も見ている人を混乱させてしまう元となると思います。 質問タイトル、本文を修正し、「解決したい問題」に焦点を絞ってください。
mememe0331

2022/07/31 02:36

ご指摘ありがとうございます。 内容を修正いたします。
退会済みユーザー

退会済みユーザー

2022/07/31 02:58 編集

ここのコメントは回答欄に移動しました。
m.ts10806

2022/07/31 03:53

細かいですが、XAMPPは各ツール、言語の集合体なので、実際に動作させてるのはPHPになるのではと。 もちろん、MySQL(MariaDB)直に実行して想定の結果が得られるSQL文を作るのは必須ではありますが。
退会済みユーザー

退会済みユーザー

2022/07/31 08:38

質問者さん、その後無言ですが、回答したのでそれに対するフィードバックを返してください。役に立った/立たなかったぐらいはすぐに返せるのでは? 役に立たなかったならどこがダメかを書くとより期待に近い回答が出てくるかも。とにかく無言は NG です。
guest

回答2

0

ベストアンサー

質問者さんの

このエラーを表示させずに、別ブラウザで「このIDは既に使用されています」のように表示させたいです。

を実現するなら、
いきなりINSERT文を実行せず、該当のテーブルに対してSELECT文にてpidの存在チェックをすれば済みます。
例えば、

sql

1SELECT COUNT(pid) AS CNT FROM products WHERE pid = 調べたいID;

を実行した結果がCNTというカラム名で参照できるので、0であれば存在しない、となります。

ところで、データベースアクセスで、フォーム入力など外部からくる変数を直接SQL文字列に使ってしまうと、
SQLインジェクションによりデータベースの情報漏洩や破壊といったことを招くためおすすめできません。

PHP: PDO::__construct - Manualのようにnew PDO() でデータベース接続して、
PHP: PDO::prepare - Manualのようにプリペアドステートメントを用意した上で、
PHP: PDOStatement::bindValue - Manualのようにパラメータと変数を紐づけしてから、
PHP: PDOStatement::execute - Manualのようにクエリーを実行します。

php

1try { 2 $st_cnt = $dbh->prepare('SELECT COUNT(pid) AS CNT FROM products WHERE pid = :pid;'); 3 $st_cnt->bindValue('pid', $pid, PDO::PARAM_STR); 4 $st_cnt->execute(); 5 $reault_cnt = $st_cnt->fetchAll(); 6 if ($reault_cnt[0]['CNT'] == 0) { // ASで指定した別名を与える 7 // 登録されていないから、INSERT文を実行 8 $st_ins = $dbh->prepare('INSERT INTO products(pid, name, const, price) VALUES (:pid, :name, :cost, :price)'); 9 $st_ins->bindValue('pid', $pid, PDO::PARAM_STR); 10 $st_ins->bindValue('name', $name, PDO::PARAM_STR); 11 $st_ins->bindValue('cost', $cost, PDO::PARAM_INT); 12 $st_ins->bindValue('price', $price, PDO::PARAM_INT); 13 $st_ins->execute(); 14 15 16 } 17 else { 18 // 登録されているので、エラー表示 19 } 20} 21catch (PDOException $e) { 22 // 略 23}

みたいな?(あくまで机上のコードなので参考程度で。トランザクション処理も足りてないし。)

fetch()やfetchAll()の第一引数がモードで、
通常 PDO::FETCH_BOTH がデフォルトで省略可能なんだけど、

結果セットに返された際のカラム名と 0 で始まるカラム番号で添字を付けた配列を返します。

ってことなので、ASで与えた別名でなくても、0でもアクセスできるかもだ。

投稿2022/08/01 01:02

編集2022/08/01 03:00
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

mememe0331

2022/08/01 02:42

ASを使うところが、自分では思いつきませんでした! 教えて頂き、ありがとうございます。
退会済みユーザー

退会済みユーザー

2022/08/01 03:32

> 該当のテーブルに対してSELECT文にてpidの存在チェックをすれば済みます。 チェックした後、他の誰かがその pid を使ったらどうなるでしょうか? 暇なサイトなのでそこまで考える必要はない? でも、やっぱりやるべきことは最初からきちんとやることをお勧めします。ホントにその pid を使っているか否かは INSERT する時点でチェックするようにしましょう。私の回答で紹介した記事のように、そういうことをやる手段はあります。
退会済みユーザー

退会済みユーザー

2022/08/01 03:54

可能性はゼロじゃないですね。 $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); してエラー発生時には例外発生させつつ、 insert intoクエリー実行時のエラーを PDOException $e でキャッチしたら良いかと。
退会済みユーザー

退会済みユーザー

2022/08/01 04:05

> 可能性はゼロじゃないですね。 だからそういうやり方を初学者に紹介してはいけないと思います。do it right the first time という言葉もあることですし。
退会済みユーザー

退会済みユーザー

2022/08/01 04:36

PHP: PDOException - Manual https://www.php.net/manual/ja/class.pdoexception.php でe->getCode()して該当のエラーコードなら、サイレント回避するためのコードを実行する、って方向性になるかなぁ、データ構造を変更しない前提なら。 ぶっちゃけ面倒なので、私ならSurferOnWwwさんの回答の主張に概ね乗っかって、 ユーザーが入力するidやコードの類をそのまま主キーに使うことは絶対避けますけどね。
guest

0

質問に貼ってある画像は phpMyAdmin のようですが、ブラウザから phpMyAdmin 経由で MySQL にアクセスして、重複する主キーで新規データを INSERT したとき、

エラーを表示させずに、別ブラウザで「このIDは既に使用されています」のように表示させたい

ということですか? 

それは 100% 絶対に不可能・・・とまで言い切る自信はありませんけど、少なくともそれに近い無理筋な話だと思いますけど。

主キーを AUTO_INCREMENT にするのが現実的な解決策だと思います。

3.6.9 AUTO_INCREMENT の使用
https://dev.mysql.com/doc/refman/8.0/ja/example-auto-increment.html


【追記】

管理者用の phpMyAdmin ではなくて、一般ユーザーが質問者さんの開発する Web アプリで MySQL を利用する時の話で、かつ、主キーを AUTO_INCREMENT にはできないという話であれば、Web アプリで対応する話になると思います。

例えば、ASP.NET MVC アプリですと以下の記事のように、 PK 制約違反例外をキャッチしてエラーメッセージを表示し、ユーザーに再入力を促すということができます。

EF Core で PK / Unique 制約違反例外をキャッチ
http://surferonwww.info/BlogEngine/post/2021/03/25/aspnet-core-validation-for-pk-and-unique-restrictions-of-sql-server.aspx

質問者さんの Web アプリが何だか分かりませんが (PHP ?)、同様なことができないか検討されてはいかがですか?

投稿2022/07/31 02:57

編集2022/07/31 03:11
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

mememe0331

2022/08/01 02:41

詳細に説明して頂き、ありがとうございます。 この情報を元に試してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問