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

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

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

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

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

9244閲覧

MySQLの二重登録を防止したい

hiziki

総合スコア54

MySQL

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

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

2クリップ

投稿2017/04/24 14:40

編集2017/05/02 06:21

###前提・実現したいこと
PHPとMySQLを使い、「楽譜管理プログラム」のデータベースを作っています。楽譜の管理クラス(大分類)と管理番号(例:P-001、C-005)二重登録したくないので、以下の構文にしてみましたが、二重登録できてしまうのと

Warning: PDOStatement::execute() expects at most 1 parameter, 2 given in /virtual/(id名)/public_html/add.php on line 52

というエラーがでました。

※ DB接続パスワードは消してます
###該当のソースコード

PHP

1<?php 2session_start(); 3error_reporting(E_ALL ^ E_NOTICE); 4 5$db['host'] = ''; 6$db['user'] = ''; 7$db['pass'] = ''; 8$db['dbname'] =''; 9 10// エラーメッセージ、登録完了メッセージの初期化 11$errorMessage = ""; 12$signUpMessage = ""; 13 14// ログインボタンが押された場合 15if (isset($_POST["signUp"])) { 16 // 1. ユーザIDの入力チェック 17 if (empty($_POST["kanriclass"])) { // 値が空のとき 18 $errorMessage = '管理クラスが未入力です。'; 19 } else { 20 if (empty($_POST["kanrino"])) { // 値が空のとき 21 $errorMessage = '管理番号が未入力です。'; 22 } else { 23 if (empty($_POST["songnamekana"])) { // 値が空のとき 24 $errorMessage = '曲名(カナ)が未入力です。'; 25 } else { 26 if (empty($_POST["songname"])) { // 値が空のとき 27 $errorMessage = '曲名が未入力です。'; 28 } 29 } 30 } 31 } 32 33 if (!empty($_POST["kanriclass"]) && !empty($_POST["kanrino"]) && !empty($_POST["songnamekana"]) && !empty($_POST["songname"])) { 34 // 入力したユーザIDとパスワードを格納 35 $kanriclass = $_POST["kanriclass"]; 36 $kanrino = $_POST["kanrino"]; 37 $songnamekana = $_POST["songnamekana"]; 38 $songname = $_POST["songname"]; 39 $memo = $_POST["memo"]; 40 41 // 2. ユーザIDとパスワードが入力されていたら認証する 42 $dsn = sprintf('mysql:host=%s;dbname=%s;charset=utf8', $db['host'], $db['dbname']); 43 44 // 3. エラー処理 45 try { 46 $pdo = new PDO($dsn, $db['user'], $db['pass'], array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); 47 48 // プリペアドステートメントを用意 49 $stmt = $pdo->prepare('SELECT COUNT(*) FROM test WHERE `kanriclass`, `kanrino` = ?, ?'); 50 51 // 「?」の部分に文字列として安全に入力をあてはめて実行 52 $stmt->execute([$kanriclass],[$kanrino]); 53 $count = (int)$stmt->fetchColumn(); 54 55 if ($count === 0) { 56 $stmt = $pdo->prepare("INSERT INTO `test`(`kanriclass`, `kanrino`, `songnamekana`, `songname`, `memo`) VALUES (?, ?, ?, ?, ?)"); 57 $stmt->bindParam(1, $kanriclass, PDO::PARAM_STR); 58 $stmt->bindParam(2, $kanrino, PDO::PARAM_INT); 59 $stmt->bindParam(3, $songnamekana, PDO::PARAM_STR); 60 $stmt->bindParam(4, $songname, PDO::PARAM_STR); 61 $stmt->bindParam(5, $memo, PDO::PARAM_STR); 62 63 $stmt->execute(); 64 $signUpMessage = '登録が完了しました。管理クラス・番号は ' . $kanriclass . '-' . $kanrino . ' です。曲名:「' . $songname . '(' . $songnamekana . ')」、また、メモとして「' . $memo . '」を追加しました。'; 65 } else { 66 $confirmerror = 'エラー:管理クラス「' . $kanriclass . ' ' . $kanrino . '」はすでに登録されています。'; 67 } 68 } catch (PDOException $e) { 69 $errorMessage = 'データベースエラー'; 70 // $e->getMessage() でエラー内容を参照可能(デバック時のみ表示) 71 echo $e->getMessage(); 72 } 73 } 74} 75?> 76 77<!doctype html> 78<html> 79<head> 80 <meta charset="UTF-8"> 81 <title>新規登録</title> 82</head> 83<body> 84<h1>新規登録画面</h1> 85<form id="loginForm" name="loginForm" action="" method="POST"> 86 <fieldset> 87 <legend>新規登録フォーム</legend> 88 <div><font color="#ff0000"><?php echo htmlspecialchars($errorMessage, ENT_QUOTES); ?></font></div> 89 <div><font color="#ff0000"><?php echo htmlspecialchars($confirmerror, ENT_QUOTES); ?></font></div> 90 <div><font color="#0000ff"><?php echo htmlspecialchars($signUpMessage, ENT_QUOTES); ?></font></div> 91 92 <label for="kanriclass">※必須※ 登録クラス</label> 93 94<input type="text" required id="kanriclass" name="kanriclass" 95 value="<?php if (!empty($_POST["kanriclass"])) { 96 echo htmlspecialchars($_POST["kanriclass"], ENT_QUOTES); 97 } ?>" placeholder="クラスを入力"> 98 <br> 99 <label for="kanrino">※必須※ 管理番号</label><input type="text" required id="kanrino" name="kanrino" 100 value="<?php if (!empty($_POST["kanrino"])) { 101 echo htmlspecialchars($_POST["kanrino"], ENT_QUOTES); 102 } ?>" placeholder="管理番号を入力"> 103 <br> 104 <label for="songnamekana">※必須※ 曲名(カナ)</label><input type="text" required id="songnamekana" name="songnamekana" 105 value="<?php if (!empty($_POST["songnamekana"])) { 106 echo htmlspecialchars($_POST["songnamekana"], 107 ENT_QUOTES); 108 } ?>" placeholder="曲名のカナを入力"> 109 <br> 110 <label for="songname">※必須※ 曲名</label><input type="text" required id="songname" name="songname" 111 value="<?php if (!empty($_POST["songname"])) { 112 echo htmlspecialchars($_POST["songname"], ENT_QUOTES); 113 } ?>" placeholder="曲名を入力"> 114 <br> 115 <label for="memo">メモ(任意)</label><textarea type="text" id="memo" name="memo" cols="50" rows="10" 116 placeholder="メモを入力"></textarea> 117 <br> 118 <input type="submit" id="signUp" name="signUp" value="新規登録"> 119 </fieldset> 120</form> 121</body> 122</html>

phpMyAdmin

SQL

1-- 2-- テーブルの構造 `test` 3-- 4 5CREATE TABLE IF NOT EXISTS `test` ( 6 `id` int(5) NOT NULL AUTO_INCREMENT, 7 `kanriclass` varchar(30) NOT NULL, 8 `kanrino` int(30) NOT NULL, 9 `songnamekana` char(100) NOT NULL, 10 `songname` char(100) NOT NULL, 11 `memo` text, 12 `kanriclassconfig` varchar(50) NOT NULL, 13 PRIMARY KEY (`id`), 14 UNIQUE KEY `id_2` (`id`), 15 UNIQUE KEY `id_3` (`id`), 16 KEY `id` (`id`) 17) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=22 ; 18 19-- 20-- テーブルのデータのダンプ `test` 21-- 22 23INSERT INTO `test` (`id`, `kanriclass`, `kanrino`, `songnamekana`, `songname`, `memo`, `kanriclassconfig`) VALUES 24(1, 'M8', 1, 'キミガヨ', '君が代', '日本の国歌。', ''), 25(3, 'M8', 3, 'アールピージー', 'RPG', '', ''), 26(4, 'M8', 3, 'アールピージー', 'RPG', '', ''), 27(5, 'M8', 5, 'サンガツココノカ', '3月9日', 'レミオロメンの楽曲', ''), 28(11, 'M8', 55, 'ア', 'あ', '', ''), 29(12, '', 0, '', '', NULL, 'M8'), 30(14, '', 0, '', '', NULL, 'P'), 31(15, '', 0, '', '', NULL, 'NK'), 32(16, 'M8', 10, 'キミガヨコウシンキョク', '君が代行進曲', '', ''), 33(17, 'M8', 15, 'ゼンゼンゼンセイ', '前前前世', '', ''), 34(18, 'M8', 15, 'ゲンロク', '元禄', '', ''), 35(19, 'M8', 0, 'ガッツ!', 'GUTS!', '', ''), 36(20, 'M8', 139, 'ガッツ!', 'GUTS!', '', ''), 37(21, 'M8', 139, 'ガッツ!', 'GUTS!', '', ''); 38 39/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 40/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 41/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

###補足情報(言語/FW/ツール等のバージョンなど)
サーバー:「XREA(s1001)」

PHPバージョン:5.5.38
phpMyAdmin:4.0.10.15

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

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

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

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

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

guest

回答2

0

UNIQUE KEY id_2 (id),

UNIQUE KEY id_3 (id),
KEY id (id)

あたりが何をしたいのかよくわかりません
kanriclass,kanrinoの組み合わせがユニークにしたいのであれば

UNIQUE(kanriclass,kanrino)

など複合ユニークインデックスをつければよいでしょう
ただしこれは二重登録をさせないだけなので、重複データが送られてきたとき
どうするかはプログラム側の問題です
INSERT IGNORE INTOで処理すれば重複データを無視しますし
PDOならrowcount()などで登録が成功したかどうかチェックします

投稿2017/04/25 01:36

yambejp

総合スコア114572

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

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

hiziki

2017/04/25 09:40

ご回答ありがとうございます。そういう構文もあるのですね!勉強になりました!ありがとうございました
guest

0

ベストアンサー

$stmt = $pdo->prepare('SELECT COUNT(*) FROM test WHERE `kanriclass`, `kanrino` = ?, ?');

これ、何がしたいのだろう、WHERE句これでいいの?

$stmt = $pdo->prepare('SELECT COUNT(*) FROM test WHERE `kanriclass` = ? AND `kanrino` = ?');

のことだろうか。

加えて、

$stmt->execute([$kanriclass],[$kanrino]);

は、もしかして

$stmt->execute([$kanriclass, $kanrino]); //$stmt->execute( array($kanriclass, $kanrino) ); // 古い書き方

のことだろうか。
execute()で渡すのは配列一つなので。

投稿2017/04/25 02:51

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

hiziki

2017/04/25 09:39

ありがとうございます!できました!
shiroyuki

2017/05/02 07:26

重複登録を防ぐのであれば、まず入れ物のtableの定義を正しいものにしてあげるべきです。 また、トランザクションを使用しているわけではないので、同時アクセス時に重複レコードが入るという抜け道が存在します。 tableの定義で制限をかけておけばどのような処理を書いても重複データが入ることは絶対にありませんし、重複時にはDBがエラーを返してくれるので、ソースコードはよりシンプルなものになり、保守性もあがります。
退会済みユーザー

退会済みユーザー

2017/05/02 07:33

phpの処理以外でもデータベースの追加や更新が起こりうるなら、 いや、起こり得なくても、 テーブルの定義はちゃんとしておいたほうが良いです。もっともです。 私の回答は、とにかく質問文にあったコードがおかしいから直したまでです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問