Проблема при добавлении данных в бд
Есть массив логов, у которых есть данные об ip, времени, url, статусе и агенте. Структура таблицы с логами:
CREATE TABLE `logs` (
`ip` varchar(32) NOT NULL,
`date` varchar(64) NOT NULL,
`url_id` int NOT NULL,
`status_id` int NOT NULL,
`agent_id` int NOT NULL
)
CREATE TABLE `agents` (
`id` int NOT NULL,
`agent` varchar(256) NOT NULL
)
CREATE TABLE `statuses` (
`id` int NOT NULL,
`status` int NOT NULL
)
CREATE TABLE `urls` (
`id` int NOT NULL,
`url` varchar(256) NOT NULL
)
Собственно url_id, status_id и agent_id это вторичные ключи для других таблиц.
Вот так пытаюсь заносить данные:
function edit_log(&$log_data)
{
$db = new PDO('mysql:host=localhost;dbname=logsdb', 'root', '');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$log_data["date"] = $log_data["date"]->format('Y-m-d H:i:s');
// Проверяем, существует ли указанный url в таблице urls
$url_check = $db->query("SELECT `id` FROM `urls` WHERE `url` = '${log_data["url"]}'");
if ($url_row = $url_check->fetch() == false) {
$db->query("INSERT INTO `urls` (`url`) VALUES ('${log_data["url"]}')");
$url_check = $db->query("SELECT `id` FROM `urls` WHERE `url` = '${log_data["url"]}'");
$url_row = $url_check->fetch();
$log_data["url"] = $url_row['id'];
} else {
$log_data["url"] = $url_row['id'];
}
// Проверяем, существует ли указанный статус в таблице statuses
$status_check = $db->query("SELECT `id` FROM `statuses` WHERE `status` = '${log_data["status"]}'");
if ($status_row = $status_check->fetch() == false) {
$db->query("INSERT INTO `statuses` (`status`) VALUES (${log_data["status"]})");
$status_check = $db->query("SELECT `id` FROM `statuses` WHERE `status` = '${log_data["status"]}'");
$status_row = $status_check->fetch();
$log_data["status"] = $status_row['id'];
} else {
$log_data["status"] = $status_row['id'];
}
// Проверяем, существует ли указанный агент в таблице agents
$agent_check = $db->query("SELECT `id` FROM `agents` WHERE `agent` = '${log_data["agent"]}'");
if ($agent_row = $agent_check->fetch() == false) {
$db->query("INSERT INTO `agents` (`agent`) VALUES ('${log_data["agent"]}')");
$agent_check = $db->query("SELECT `id` FROM `agents` WHERE `agent` = '${log_data["agent"]}'");
$agent_row = $agent_check->fetch();
$log_data["agent"] = $agent_row['id'];
} else {
$log_data["agent"] = $agent_row['id'];
}
}
$count = count($logs); // Количество прочитанных логов
if ($count) {
$log_data = $logs[0];
edit_log($log_data);
$log_string = "('${log_data["ip"]}', '${log_data["date"]}', ${log_data["url"]}, ${log_data["status"]}, ${log_data["agent"]})";
for ($i = 1; $i < $count; $i++) {
$log_data = $logs[$i];
edit_log($log_data);
$log_string .= ", ('${log_data["ip"]}', '${log_data["date"]}', ${log_data["url"]}, ${log_data["status"]}, ${log_data["agent"]})";
}
$sql_query = "INSERT INTO `logs`(`ip`, `date`, `url_id`, `status_id`, `agent_id`) VALUES " . $log_string;
$db->query($sql_query);
}
то есть в функции я проверяю, есть ли в таблице запись об url/статусе/агенте, и если нет, то добавляю их и беру id вставленной записи(авто-инкрементируемый), который потом вставляю в главную таблицу.
Но почему-то при выполнении появляется ошибка:
<b>Fatal error</b>: 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 ', 2), ('213.87.153.60', '2020-09-01 03:16:09', 3, , ), ('46.229.168.163', '2020-' at line 1
то есть почему-то в главную таблицу не вставляются данные о вторичных ключах
Подскажите, в чём может быть проблема?
Ответы (1 шт):
Структура.
CREATE TABLE `agents` (
`agent_id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
`agent` varchar(256) NOT NULL UNIQUE
);
CREATE TABLE `statuses` (
`status_id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
`status` int NOT NULL UNIQUE
);
CREATE TABLE `urls` (
`url_id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
`url` varchar(256) NOT NULL UNIQUE
);
CREATE TABLE `logs` (
`ip` varchar(32) NOT NULL,
`date` varchar(64) NOT NULL,
`url_id` int NOT NULL, FOREIGN KEY (url_id) REFERENCES urls (url_id),
`status_id` int NOT NULL, FOREIGN KEY (status_id) REFERENCES statuses (status_id),
`agent_id` int NOT NULL, FOREIGN KEY (agent_id) REFERENCES agents (agent_id)
);
Вставка:
INSERT IGNORE INTO agents (agent) VALUES ($agent);
INSERT IGNORE INTO statuses (status) VALUES ($status);
INSERT IGNORE INTO urls (url) VALUES ($url);
INSERT INTO logs (ip, `date`, url_id, status_id, agent_id)
SELECT urls.url_id, statuses.status_id, agents.agent_id
FROM urls
CROSS JOIN statuses
CROSS JOIN agents
WHERE urls.url = $url
AND statuses.status = $status
AND agents.agent = $agent;
А всю вон ту ерунду с проверками "существует или нет" - в мусор.
И если используешь PDO, то надо не в тело запроса вставлять значения (здравствуй, инъекция!), а передавать значения в подготовленный запрос как параметры.