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

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

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

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

SQL

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

PHP

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

Q&A

解決済

2回答

1535閲覧

PHPにおいてPDOで変数を用いてDBをUPDATEしたいがうまくいきません。

janhampino

総合スコア6

PDO

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

SQL

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

PHP

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

0グッド

0クリップ

投稿2020/10/13 07:57

編集2020/10/13 08:23

前提・実現したいこと

PHPにてDBに対してUPDATEを実行したいのですが、PDOを用いた際にカラムや値に変数をバインドする方法がうまくいかない状態です。
やりたいこととしてはex_tableの指定した日付の列の2つのカラムの値をプラス1するように更新したいと思っています。

以下のような方法を試しているのですがどこがおかしいかお教え頂けたら幸いです。

該当のソースコード

php

1 $str_date = '2020-10-10';//ここで日付指定 2 3 //カラム名を指定する変数 4 $sports = 'tennis'; 5 $food = 'rice'; 6 7 $dbh = db_connect(); 8 9 //以下が問題の箇所 10 $statement = $dbh->prepare('UPDATE ex_table SET :sports = :sports + 1, :food = :food + 1, WHERE date = :str_date'); 11 12 $statement->bindParam(:sports, $sports, PDO::PARAM_INT); 13 $statement->bindParam(:food, $food, PDO::PARAM_INT); 14 $statement->bindParam(:str_date, $str_date, PDO::PARAM_INT); 15 $statement->execute(); 16 $dbh = null; 17 18 19 20 //また別の方法として以下のパターンも試してみました 21 $statement = $dbh->prepare('UPDATE ex_table SET ? = ? + 1, ? = ? + 1, WHERE date = ?'); 22 23 $statement->bindParam(1, $sports, PDO::PARAM_INT); 24 $statement->bindParam(2, $sports, PDO::PARAM_INT); 25 $statement->bindParam(3, $food, PDO::PARAM_INT); 26 $statement->bindParam(4, $food, PDO::PARAM_INT); 27 $statement->bindParam(5, $str_date, PDO::PARAM_INT); 28 $statement->execute(); 29 $dbh = null; 30 31 32 //ご回答をいただく中で以下をさらに試してみましたので追記します 33 $statement = $dbh->prepare('UPDATE ex_table SET sports = :sports + 1, food = :food + 1, WHERE date = :str_date'); 34 35 $statement->bindColumn('sports', $sports); 36 $statement->bindColumn('food', $food); 37 $statement->bindParam(':sports', $sports, PDO::PARAM_INT); 38 $statement->bindParam(':food', $food, PDO::PARAM_INT); 39 $statement->bindParam(':str_today', $str_date, PDO::PARAM_STR); 40 $statement->execute(); 41 $dbh = null;

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

PHP 7.3
DBはMySQL
フレームワークなど無し

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

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

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

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

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

guest

回答2

0

ベストアンサー

カラムやテーブル名にプリペアドステートメントのパラメータは利用できません。
それを除けばSQLも結局は文字列の集合体なので普通にPHPで変数と文字列連結する形で入れられます。

が、

$sports = tennis;

$food = rice;

$もなくクォーテーションに囲まれてもないので定数として扱われますが、こちら本当にそういうコードなのでしょうか。

投稿2020/10/13 07:59

編集2020/10/13 08:06
m.ts10806

総合スコア80850

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

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

janhampino

2020/10/13 08:12

失礼しました、こちらに掲載するために変数名などを変更した際に書き忘れておりました。 ご指摘ありがとうございます。修正させていただきます。
m.ts10806

2020/10/13 08:13

あまりなおすと、要件から遠くなるのでなるべくそのままコピペされた方が良いかと思います(今回のようにあらぬ詮索を強います)
janhampino

2020/10/13 08:20 編集

承知いたしました。ご指摘ありがとうございます。 以降気をつけます。 また、 >カラムやテーブル名にプリペアドステートメントのパラメータは利用できません。 これを受けましてbindColumnを使用して実現なども不可能なのでしょうか? 私自身PDOにおいての理解が足りず、基本的な部分で間違っているのかもしれませんが コードに追記をしたのでもし良ければご意見いただければと思います。
m.ts10806

2020/10/13 08:24

bindにこだわる理由が分かりませんが、既に書いているように文字列連結で投入すれば良いだけです。 'UPDATE ex_table SET '.$sports.' = '.$sports.' + 1, '.$food.' = '.$food.' + 1, WHERE date = :str_date' 「値」であるstr_dateのみbindすることになります。
m.ts10806

2020/10/13 08:26

なのでsportsもfoodもbind不要ですし、できません。
janhampino

2020/10/13 08:53 編集

迅速なご回答ありがとうございます。 >既に書いているように文字列連結で投入すれば良いだけです。 そうなのですね。セキュリティにおいてSQL文内にそのまま変数を組み込むのが危険な記述なのではないかなどと思っていたためなんとかバインドできないかと考えておりました。 一旦こちらの方法で試してみます。
m.ts10806

2020/10/13 09:12

システムで固定値払い出しのものに驚異はないかと思います。あくまで「何がくるか分からないユーザーの入力」なので、エスケープする必要があります。 もしカラム名やテーブル名がユーザー入力を受け付ける仕様なのでしたら、設計を見直す必要があります。
janhampino

2020/10/13 09:27

>システムで固定値払い出しのものに驚異はないかと思います。あくまで「何がくるか分からないユーザーの入力」なので、エスケープする必要があります こちらありがとうございます。この辺りのどのようなケースこの実装が必要になるかという部分の理解が私自身足りておりませんでした。 今回は固定値なので実装としては必要なさそうなので先程いただいた方法で実装していこう思います。 また試しにカラム部分は固定で値の部分をバインドして動かしてみると無事値が更新されたので、値に関しての記述方法は間違ってはなさそうでした。 PDOを使用してカラム部分のバインドは不可能であるとのこと学ばせていただきました。誠にありがとうございます!
m.ts10806

2020/10/13 09:30

一点忘れてました。 注意ですが、bindParamよりbindValueのほうが副作用なく使えるようです。 違いなど調べて納得した上で移行を考えてみてください。
janhampino

2020/10/13 09:35

>注意ですが、bindParamよりbindValueのほうが副作用なく使えるようです。 こちらありがとうござます。 承知しました、こちらも調査して試してみる事にいたします。
guest

0

ex_tableのtennisとriceっていうカラムの値をプラス1するっていうのは、そのカラムはINTってことでいいですか?

PARAM_INTに指定はしてあるのであれなんですが、
$sports = 'tennis'っていうStringが入ってて、tennis + 1っていう感じになっちゃってると思うんですけど、、、、

UPDATE ex_table SET tennis = tennis + 1, rice = rice + 1 WHERE date = '2020-10-10';
ってことですよね?

これだとうまくいかないと思うんですが?

間違ってたらごめんなさいww

ついでに
bindParam(':sports', $sports, PDO::PARAM_INT)じゃないかな?

投稿2020/10/13 08:39

Fetherion

総合スコア60

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

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

janhampino

2020/10/13 09:13

ご回答ありがとうござます。 >PARAM_INTに指定はしてあるのであれなんですが、 >$sports = 'tennis'っていうStringが入ってて、tennis + 1っていう感じになっちゃってると思うんですけど、、、、 >UPDATE ex_table SET tennis = tennis + 1, rice = rice + 1 WHERE date = '2020-10-10'; ってことですよね?これだとうまくいかないと思うんですが? こちらにつきまして、 UPDATE ex_table SET $sports = $sports + 1, $food = $food + 1, WHERE date = $str_date; 元々上記のようなSQLを書いて実行しており、この場合は問題なく意図した動作で動いておりました。 SQLインジェクションに関しての記事を見た際にSQL文にそのまま変数渡すのはセキュリティ的によくないのかなと思い今回バインドして変数を渡そうとしておりました。(この経緯を書かずに申し訳ありません。。) >bindParam(':sports', $sports, PDO::PARAM_INT)じゃないかな? すみません、こちらについてはどのようなご指摘でしょうか? 「$statement->」部分を取り除くという意味でしょうか?
m.ts10806

2020/10/13 09:14

>間違ってたらごめんなさいww はい。間違ってます。 仰っているのは、tennis = 'tennis' + 1のことで tennis = tennis + 1 となると「tennisの現在値に1足した数を投入」という意味になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問