Как PDO знает последний вставленный id в MySQL?
РЕДАКТИРОВАТЬ: Этот заголовок вопроса первоначально был: Как Doctrine знает последний вставленный id в MySQL? и был связан с Mapper Doctrine ORM. После некоторого копания я узнал, что этот вопрос не связан с Doctrine, а с PDO_MySQL, MySQL C API и, наконец, - с обменом данными между клиентом и сервером MySQL. Я решил изменить название, так что, возможно, кто-то найдет ответ на его/ее вопрос.
Для тех, кто не использует Доктрину: мне было любопытно, почему рев:
mysql_query("INSERT INTO category (name) VALUES('cat')");
echo mysql_insert_id();
или аналогичный:
$pdo->exec("INSERT INTO category (name) VALUES('cat')");
echo $pdo->lastInsertId();
приведет только к одной позиции (без отдельной SELECT LAST_INSERT_ID()
) в log:
1701 Query INSERT INTO category (name) VALUES ('cat')
Оригинальный вопрос:
У меня есть 2 таблицы:
category(id,name)
product(id, name, categoryId)
Я создал объект и объект объекта категории. Я присвоил объект категории объекту продукта. Я не установил никаких идентификаторов:
$product = new Product();
$product->name = 'asdf';
$category = new Category();
$category->name = 'cat';
$product->Category = $category;
После этого я сбросил соединение и проверил журналы MySQL:
1684 Query START TRANSACTION
1684 Query INSERT INTO category (name) VALUES ('cat')
1684 Query INSERT INTO product (name, categoryid) VALUES ('asdf', '312')
1684 Query COMMIT
Как Doctrine знает, что только что созданный идентификатор категории - 312? В журналах больше ничего нет.
Ответы
Ответ 1
Я провел некоторое исследование и просмотрел некоторый исходный код, поэтому мой ответ может быть немного неправильным и не точным.
Прежде всего, это не связано с Доктриной. Doctrine использует PDO_MYSQL. Но внутри PDO_MYSQL использует ту же функцию, что и функция mysql_insert_id
- встроенная функция API MySQL C - mysql_insert_id
.
Причина отсутствия отдельного SELECT LAST_INSERT_ID()
заключается в том, что после выполнения оператора (в моем примере INSERT
) сервер отвечает данными и некоторыми другими вещами, включенными в пакет OK), включая insert_id
. Поэтому, когда мы запускаем mysql_insert_id()
, мы не подключаемся к серверу, для получения insert_id
- библиотеки mysql не нужно это делать - у этого уже есть это значение, сохраненное от последнего выполнения запроса (по крайней мере, я думаю, это после анализа файл libmysql.c
)
Здесь описывается пакет OK: Пакеты общего ответа MySQL - пакет OK
Ответ 2
Возможно, вызывая http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
Ответ 3
last_insert_id
работает только для столбцов AUTO_INCREMENT
. Он не будет работать, если вы введете значение вручную в столбец AUTO_INCREMENT
.
Доктрина будет работать, потому что это точно так же, как присвоение ей NULL
(хотя вы никогда специально не пишете это). Это вызывает автоматический приращение и дает значение для last_insert_id()
.
Здесь я включил jpg, чтобы вы могли его увидеть. Надеюсь, это поможет!
![enter image description here]()