Синтаксическая ошибка или нарушение доступа: 1064 - PDO отказывается выполнять несколько запросов (включая CREATE TEMPORARY TABLE) - PullRequest
1 голос
/ 08 мая 2019

Я пытаюсь выполнить следующий запрос, используя PDO в PHP. Запрос работает нормально и без каких-либо упомянутых проблем при применении его в PhpMyAdmin. Тем не менее, он показывает следующую ошибку при выполнении его в PHP:

 Fatal error: Uncaught PDOException: 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 'CREATE TEMPORARY TABLE IF NOT EXISTS temp2 AS SELECT COUNT(*) AS total_visits, s' at line 1

Код прост, я не уверен, требуется ли структура таблицы, но предоставлю ее в конце этого вопроса

    $sql = "CREATE TEMPORARY TABLE IF NOT EXISTS temp1 AS SELECT COUNT(*) AS total_views, series_id FROM my_app_stats d1 WHERE 1 = 1 AND d1.stats_type = 0 AND d1.created_at_text = DATE_FORMAT(NOW(), '%Y-%m-%d') GROUP BY series_id; CREATE TEMPORARY TABLE IF NOT EXISTS temp2 AS SELECT COUNT(*) AS total_visits, series_id FROM my_app_stats d2 WHERE 1 = 1 AND d2.stats_type = 1 AND d2.created_at_text = DATE_FORMAT(NOW(), '%Y-%m-%d') GROUP BY series_id; ALTER TABLE `temp1` ADD INDEX `temp1_idx_id` (`series_id`); ALTER TABLE `temp2` ADD INDEX `temp2_idx_id` (`series_id`); SELECT database_series.id, (SELECT dusers.user_name FROM my_app_users dusers WHERE dusers.id = database_series.series_owner) user_name, database_series.series_title, temp1.total_views, temp2.total_visits FROM my_app_series database_series LEFT JOIN temp1 ON temp1.series_id = database_series.id LEFT JOIN temp2 ON temp2.series_id = database_series.id ORDER BY total_views DESC, total_visits DESC LIMIT 10";
    $query = $this->conn->prepare($sql);
    $query->execute();
    $data = $query->fetchAll(PDO::FETCH_ASSOC);
    $query->closeCursor();
    return $data;

my_app_users

id | user_name

my_app_stats

id | series_id | created_at (timestamp) | created_at_text (text, formatted as y-m-d) 

my_app_series

id | series_owner

1 Ответ

1 голос
/ 08 мая 2019

Нельзя использовать prepare() с серией нескольких операторов.MySQL не поддерживает его.

Это почти дубликат PHP MySQLi подготовленного выражения multi_query , но это для mysqli.Это не имеет значения, это ограничение MySQL, а не интерфейса PHP.

В любом случае нет причин для подготовки нескольких операторов SQL за один вызов.

Вы должны выполнять их по одному утверждению за раз.

Относительно вашего комментария: Да, они все связаны, и вы можете полагаться на временные таблицы, оставшиеся доступными, пока вы запрашиваете их, используято же самое соединение у вас в $this->conn.Временные таблицы не исчезнут, если вы не закроете соединение (или, конечно, намеренно НЕ УДЕРЖИТЕ временные таблицы).

Пример:

$sql = "CREATE TEMPORARY TABLE IF NOT EXISTS temp1 AS 
  SELECT COUNT(*) AS total_views, series_id FROM my_app_stats d1 
  WHERE 1 = 1 AND d1.stats_type = 0 
    AND d1.created_at_text = DATE_FORMAT(NOW(), '%Y-%m-%d') 
  GROUP BY series_id";
$this->conn->exec($sql);

$sql = "CREATE TEMPORARY TABLE IF NOT EXISTS temp2 AS 
  SELECT COUNT(*) AS total_visits, series_id FROM my_app_stats d2 
  WHERE 1 = 1 AND d2.stats_type = 1 
    AND d2.created_at_text = DATE_FORMAT(NOW(), '%Y-%m-%d') 
  GROUP BY series_id";
$this->conn->exec($sql);

$sql = "ALTER TABLE `temp1` ADD INDEX `temp1_idx_id` (`series_id`)";
$this->conn->exec($sql);

$sql = "ALTER TABLE `temp2` ADD INDEX `temp2_idx_id` (`series_id`)";
$this->conn->exec($sql);

$sql = "SELECT 
    database_series.id,
    (SELECT dusers.user_name FROM my_app_users dusers 
     WHERE dusers.id = database_series.series_owner) AS user_name, 
    database_series.series_title, 
    temp1.total_views, 
    temp2.total_visits 
  FROM my_app_series database_series 
  LEFT JOIN temp1 ON temp1.series_id = database_series.id 
  LEFT JOIN temp2 ON temp2.series_id = database_series.id 
  ORDER BY total_views DESC, total_visits DESC LIMIT 10";
$query = $this->conn->prepare($sql);
$query->execute();
$data = $query->fetchAll(PDO::FETCH_ASSOC);
return $data;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...