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

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

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

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

PHP

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

Q&A

解決済

2回答

4243閲覧

PHPのPDOでprepare(予約文)が実行できない

cometbeet

総合スコア21

MySQL

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

PHP

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

0グッド

1クリップ

投稿2018/12/21 02:45

前提・実現したいこと

現在phpでMySQLのPDOのクラスを作っており、その中でauto_incrementの振り直しをする関数を作成したいと思っています。
振り直しのやり方についてネットで調べたら以下のようなプログラムを見つけました。

MySQL

1set@i :=0; 2update テーブル名 set カラム名 = (@i := @i + 1); 3alter table テーブル名 auto_increment = 1;

これを実装しようとしています。
その際2行目でエラーが発生しました。

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

このクラスから作成したインスタンスで関数を実行させるようにしたらブラウザが真っ白になっていました。
php ファイル名.phpを実行して確認すると以下のエラーが出ました。

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''テーブル名' set カラム名 = (@i := @i + 1)' at line 1

どうやらテーブル名の前後にクォーテーションが入ってしまっていてエラーが出ているように見えます
多分変数に入っているものがそのまま入ったからクォーテーションも入ってしまったのだと思います。
ここでどのようにしたらクォーテーションを抜いた分だけ入るのかわかりませんでした。

該当のソースコード

php

1class pdoclass{ 2 public $host = 'localhost'; 3 public $username = 'ユーザー名'; 4 public $passwd = 'パスワード'; 5 public $dbname = 'データベース名'; 6 public $tablename = 'テーブル名'; 7 function pdo(){ 8 $dsn = 'mysql:dbname='.$this->dbname.';host='.$this->host.';charset=utf8mb4'; 9 try{ 10 $pdo = new PDO($dsn, $this->username, $this->passwd, [ 11 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, 12 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, 13 ] 14 ); 15 }catch(PDOException $e){ 16 exit('データベース接続失敗'.$e->getMessage()); 17 } 18 return $pdo; 19 } 20 function increment(){ 21 $pdo = $this->pdo(); 22 try{ 23 $stmt = $pdo->query('SET @i := 0 '); 24 $stmt = $pdo->prepare('update ? set カラム名 = (@i := @i + 1)'); 25 $stmt->bindValue(1,$this->tablename, PDO::PARAM_STR); 26 $stmt->execute(); 27 $stmt = $pdo->prepare('alter table ? auto_increment = 1'); 28 $stmt->bindValue(1,$this->tablename, PDO::PARAM_STR); 29 $stmt->execute(); 30 }catch(PDOException $e){ 31 exit('失敗しました'.$e->getMessage()); 32 } 33 } 34}

試したこと

以下のように変数を使わず直接クエリを実行するようにしたらエラーは起きませんでした。

$stmt = $pdo->query('update テーブル名 set カラム名 = (@i := @i +1)');

また2行目でエラーが起きてしまっているので同じようになると思い3行目のexecuteはコメントアウトしている状態です。

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

phpのバージョン
PHP 7.2.13-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Dec 7 2018 08:07:08) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.13-1+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies
with Xdebug v2.6.1, Copyright (c) 2002-2018, by Derick Rethans

MySQLのバージョン
mysql Ver 14.14 Distrib 5.7.24, for Linux (x86_64) using EditLine wrapper

参考にしたサイト
https://www.surf-life.blue/226
https://qiita.com/mpyw/items/b00b72c5c95aac573b71

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

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

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

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

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

guest

回答2

0

ベストアンサー

update ?

prepareが投入できるのはあくまでデータだけです
テーブル名を置き換えるのには使えません

テーブル名を外から持ってきていておらずセキュアなら

PHP

1$stmt = $pdo->query('update `'.$this->tablename.'` set カラム名 = (@i := @i + 1)');

で、よいでしょう

投稿2018/12/21 02:51

yambejp

総合スコア114777

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

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

cometbeet

2018/12/21 03:01

ありがとうございます。無事エラーが出なくなりました。 ちなみになんですが予約文を使ってbindValueに文字列が入った変数を入れることはあるのでしょうか。 今回の解決法を見ていると変数があるなら直接結合させたほうがよいように見えたので。
yambejp

2018/12/21 03:04

> 変数があるなら直接結合させたほうがよい そんなことはありません。 外部から来るデータは常に攻撃性をもった汚染されたものだと認識し データに関してはすべてprepareで処理するのが正しい処理です
cometbeet

2018/12/21 03:06

あ、確かにテーブル名とユーザーが入力するデータでは扱いが別になりますね。 すみませんでした。 回答ありがとうございます。
guest

0

tablename内容は文字として扱うと当然文法エラーです。
prepareではなく、tablenameの内容を文字列としてSQL文組み立てれば良いかと。

投稿2018/12/21 02:53

sazi

総合スコア25173

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問