Основы программирования в Linux
if (mysql_real_connect(&my_connection, "localhost","rick", "secret", "foo", 0, NULL, CLIENT_FOUND_ROWS)) {Если восстановить данные в вашей базе данных и затем выполнить программу с приведенным изменением, она сообщит о четырех измененных строках.
Последняя странность функции
проявляется при удалении информации из базы данных. Если вы удаляете данные с помощью условияmysql_affected_rows,WHEREвернет ожидаемое вами количество удаленных строк. Но если в оператореmysql_affected_rowsнет условияDELETE, будут удалены все строки, но в сообщении программы о количестве строк, затронутых запросом, будет указан ноль. Это происходит потому, что MySQL оптимизирует удаление всех строк, заменяя многократные построчные удаления.WHEREНа подобное поведение не влияет флаг
.CLIENT_FOUND_ROWSЧто же вы вставили?Существует небольшая, но важная особенность вставки данных. Ранее мы упоминали столбец типа
, в который MySQL автоматически вставляет идентификаторы. Это свойство весьма полезно, особенно при наличии нескольких пользователей.AUTO_INCREMENTРассмотрим определение таблицы еще раз:
CREATE TABLE children (childno INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,fname VARCHAR(30),age INTEGER);Как видите, столбец
— поле типаchildno. Это замечательно, но когда вы вставили строку, как узнать, какой номер присвоен ребенку, чье имя вы только что вставили?AUTO_INCREMENTМожно выполнить оператор
для того чтобы извлечь данные, отобранные по имени ребенка. Но это очень неэффективный способ и не гарантирующий уникальности выбора: допустим, что у вас есть два ребенка с одним и тем же именем. Или несколько пользователей могли быстро вставить данные, и появились другие добавленные строки между вашим оператором обновления и операторомSELECT. Поскольку выяснение значения столбца типаSELECT— столь распространенная проблема, MySQL предлагает специальное решение в виде функцииAUTO_INCREMENT.LAST_INSERT_ID()Когда MySQL вставляет данные в столбец типа
, она отслеживает для каждого пользователя последнее присвоенное ею значение. Программы пользователей могут узнать его, просто используя в оператореAUTO_INCREMENTспециальную функциюSELECT, которая действует немного похоже на псевдостолбец.LAST_INSERT_ID()Выполните упражнение 8.2.
Упражнение 8.2. Извлечение ID, сгенерированного в столбце типаAUTO_INCREMENTВы сможете увидеть, как это работает, вставив несколько значений в вашу таблицу и затем применив функцию
.LAST_INSERT_ID()mysql> <b>INSERT INTO children(fname, age) VALUES('Tom', 13); </b>Query OK, 1 row affected (0.06 sec)mysql> <b>SELECT LAST_INSERT_ID();</b>+------------------+| last_insert_id() |+------------------+| 14 |+------------------+1 row in set (0.01 sec)mysql> <b>INSERT INTO children(fname, age) VALUES('Harry', 17);</b>Query OK, 1 row affected (0.02 sec)mysql> <b>SELECT LAST_INSERT_ID();</b>+------------------+| last_insert_id() |+------------------+| 15 |+------------------+1 row in set (0.00 sec)mysql>Как это работает
При каждой вставке строки MySQL выделяет новое значение для столбца
и запоминает его, поэтому вы сможете узнать это значение с помощью функцииid.LAST_INSERT_ID()Если хотите поэкспериментировать, чтобы убедиться в уникальности возвращаемого номера в вашем сеансе, откройте еще один сеанс и вставьте другую строку. В исходном сеансе повторите выполнение оператора
. Вы увидите, что номер не изменился, поскольку возвращаемый номер — последний, добавленный в текущем сеансе. Но если вы выполните операторSELECT LAST_INSERT_ID();, то увидите, что в другом сеансе действительно были вставлены данные.SELECT * FROM childrenВыполните упражнение 8.3.
Упражнение 8.3. Использование автоматически формируемых ID в программе на СВ этом примере вы измените вашу программу insert1.c, чтобы посмотреть, как она работает на С. Ключевые изменения выделены цветом. Назовите откорректированную программу insert2.c.
#include <stdlib.h>#include <stdio.h>#include "mysql.h"int main(int argc, char *argv[]) {MYSQL my_connection;<i> MYSQL_RES* res_ptr;</i><i> MYSQL_ROW sqlrow;</i>int res;mysql_init(&myconnection);if (mysql_real_connect(&my_connection, "localhost","rick", "bar", "rick", 0, NULL, 0)) {printf("Connection success\n");res = mysql_query(&my_connection,"INSERT INTO children(fname, age) VALUES('Robert', 7)");if (!res) {printf("Inserted %lu rows\n",(unsigned long)mysql_affected_rows(&my_connection));} else {