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

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

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

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

SQL

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

PHP

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

データベース

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

Q&A

解決済

3回答

3045閲覧

【PHP・MySQL】SQLSTATE[42000]のSQL構文エラーが発生する

youplus40

総合スコア19

MySQL

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

SQL

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

PHP

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

データベース

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

0グッド

0クリップ

投稿2020/10/21 07:20

前提・実現したいこと

PHPで店舗検索の機能が以前実装されており、今回バージョンが上がったローカル環境下で動くか確認したところ、
下記のエラーが発生しております。
エラーがどこで起きているのか、教えていただきたいです。

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

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''0', '20'' at line 1

該当のソースコード

PHP

1 /** 2 * お店情報を取得。 3 * 4 * @param Nagi_DB $db データベースオブジェクト 5 * @param integer $start 開始 6 * @param integer $length 取得数 7 * @param array $cond 取得条件 8 * @return array お店情報を格納した配列 9 * @throws データベースとのやり取りに失敗 10 */ 11 public static function get($db, $start, $length, $cond = array()) 12 { 13 try { 14 $params = array(); 15 $table = ABAHOUSE_Shop_DB::getTableName(self::$_language, 'shop'); 16 $sql = 'SELECT DISTINCT * FROM `' . $table . '` '; 17 if ($cond) { 18 $sql .= 'WHERE '; 19 $where = ''; 20 foreach ($cond as $k => $t) { 21 if ($where) { 22 $where .= 'AND '; 23 } 24 if ($k === 'area') { 25 if (!is_array($t)) { 26 $where .= '`area_id` = ? '; 27 $params[] = ABAHOUSE_Shop_Area::getId($db, $t); 28 } else 29 { 30 $tmp = ''; 31 foreach ((array)$t as $v) { 32 $tmp .= '?,'; 33 $params[] = $v; 34 } 35 $where .= '`area_id` IN (' . trim($tmp, ',') . ') '; 36 } 37 } 38 if ($k === 'genre') { 39 $where .= 'FIND_IN_SET(?, `kind`) '; 40 $params[] = $t; 41 } 42 if ($k === 'shop') { 43 $where .= '(FIND_IN_SET(?, `category`) OR FIND_IN_SET(?, `shop_brand`)) '; 44 $params[] = $t; 45 $params[] = $t; 46 } 47 if ($k === 'brand') { 48 $where .= '(`category` LIKE ? OR `brand` LIKE ?) '; 49 $params[] = '%' . $t . '%'; 50 $params[] = '%' . $t . '%'; 51 } 52 } 53 $sql .= $where; 54 } 55 $params[] = $start; 56 $params[] = $length; 57 58 $sql .= 'ORDER BY `area_id` LIMIT ?, ?'; 59 60 $stmt = $db->prepare($sql); 61 $stmt->execute($params); 62 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); 63 64 $result = array(); 65 if ($rows) { 66 foreach ($rows as $row) { 67 $shop = new ABAHOUSE_Shop(); 68 $shop->name = $row['name']; 69 $shop->address = $row['address']; 70 $shop->map = $row['map']; 71 $shop->tel = $row['tel']; 72 //$shop->blog = $row['blog']; 73 $shop->blog = $row['blog'] ? explode(',', $row['blog']) : null; 74 $shop->site = $row['site']; 75 $shop->hours = $row['hours']; 76 $shop->shopBrand = explode(',', $row['shop_brand']); 77 $shop->kind = explode(',', $row['kind']); 78 $shop->brand = explode(',', $row['brand']); 79 $shop->category = explode(',', $row['category']); 80 $result[] = $shop; 81 } 82 } 83 return $result; 84 } 85 catch (PDOException $e) { 86 throw $e; 87 } 88 } 89

試したこと

以前の環境下では問題なく、動いていますので、環境が変わったことによるコードの修正が必要のようです。
また、DBをMariaDBからMySQLに変更しましたが、同様にエラーが発生しました。

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

以前の環境
・apache 2.2
・PHP 5.1.6
・mysql 不明
・Linux (CentOS6.7)

現在のローカル環境
・apache 2.4.46
・PHP 7.4.11
・MariaDB 10.4.14
・Windows (XAMPP3.2.4)

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

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

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

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

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

guest

回答3

0

ざっと見た感じprepare処理に関して

LIMIT ?, ?

Limit処理はINT型を指定しないとエラーになります
型付の指定をするか、行儀悪いですがキャストしたint値を
そのまま埋め込んでください

投稿2020/10/21 07:29

yambejp

総合スコア114883

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

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

yambejp

2020/10/21 08:16

もしかしたらATTR_EMULATE_PREPARESの設定だけで回避できるかもしれません $db->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
youplus40

2020/10/21 08:30

回答ありがとうございます。 いただいたコードをfunctionの中に入れたところ、問題なく動くようになりました。
guest

0

ベストアンサー

PDOStatement::execute

パラメータ ¶

input_parameters
実行される SQL 文の中のバインドパラメータと同数の要素からなる、 値の配列。すべての値は PDO::PARAM_STR として扱われます。

の仕様により、LIMIT句に対して文字列をバインドしてしまった結果
LIMIT '0' , '20'となり、SQL文法エラー(LIMIT句に文字列は指定できない)が発生しています。

対応としては、多分こんな感じで行けそうな気がしますが、execute()$paramsを渡すのではなく、都度都度正しい型を指定してbindValue()する方が事故が少ないと思います。

PHP

1 $params[] = $start; 2 $params[] = $length; 3 4 $sql .= 'ORDER BY `area_id` LIMIT ?, ?'; 5 6 $stmt = $db->prepare($sql); 7 $stmt->execute($params); 8 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); 9

PHP

1// $params[] = $start; 2// $params[] = $length; 3 4 $sql .= 'ORDER BY `area_id` LIMIT ?, ?'; 5 6 $stmt = $db->prepare($sql); 7 foreach($params as $index => $param){ 8 $bindIndex = $index+1; 9 $stmt->bindValue($bindIndex,$param); 10 } 11 $stmt->bindValue($bindIndex+1,$start,PDO::PARAM_INT); 12 $stmt->bindValue($bindIndex+2,$length,PDO::PARAM_INT); 13// $stmt->execute($params); 14 $stmt->execute(); 15 $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); 16

投稿2020/10/21 07:51

tanat

総合スコア18713

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

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

sazi

2020/10/21 08:00

@tanatさん PHP詳しくないのでご教示下さい。 これって、DBの環境を変えて発生するものなのでしょうか?
tanat

2020/10/21 08:08

>saziさん そこ(なんで以前は動いていたか)は私も今一つ確証が持てていないところなのですが、 DB環境というよりはPHPの設定で https://www.php.net/manual/ja/pdo.setattribute.php の PDO::ATTR_EMULATE_PREPARES あたりの値が違っていて、プレースホルダへのバインド時の挙動が違ってたとかはあり得るのかなと・・・
sazi

2020/10/21 08:10

ですよね。 ご教示ありがとうございました。
yambejp

2020/10/21 08:18

あ、ATTR_EMULATE_PREPARESの件はすでにこちらに書かれていますね・・・
tanat

2020/10/21 08:22

>yambejpさん 以前動いていたのなら、ATTR_EMULATE_PREPARESだけで行けそうな気もしますよね。
youplus40

2020/10/21 08:35

>tanatさん 回答ありがとうございます。 いただいたコードで動きました。また、yambejpさんからいただいたコードでも動いたので、 tanatさんの考えの通り、ATTR_EMULATE_PREPARESがエラーの原因だったようです。
tanat

2020/10/21 08:45

フィードバックありがとうございます。 解決して良かったです。 どちらにしても $db->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); は設定しておいた方が良いので 参照: https://teratail.com/questions/233051 設定した状態で動作確認されるのが良いかと思います。
guest

0

文法エラーですから、実行しているSQL文を取得し、そのローカル環境で直接SQLを実行してエラーの詳細を確認しましょう。

エラーでは、''0', '20''とありますので、内容的にはarea_id IN (' . trim($tmp, ',') . ') などの部分では無いかと思います。
正しくは、'0', '20'のように展開されるべきですけど、DBの違いで発生するようなものでは無い気がしますが。

投稿2020/10/21 07:27

編集2020/10/21 07:36
sazi

総合スコア25197

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問