Получить сгенерированный uuid после вставки php

У меня есть тип поля таблицы varchar (36), и я хочу сгенерировать его динамически с помощью mysql, поэтому я использовал этот код:

$sql_code = 'insert into table1 (id, text) values (uuid(),'some text');'; mysql_query($sql_code); 

как я могу получить сгенерированный uuid сразу после вставки записи?

  1. char(36) лучше
  2. ты не можешь. Единственным решением является выполнение 2 разделенных запросов:

    • SELECT UUID()
    • INSERT INTO table1 (id, text) VALUES ($uuid, 'text')

где $ uuid – это значение, полученное на первом шаге.

Вы можете делать все, что вам нужно, с помощью триггеров SQL. Следующий SQL добавляет триггер на tablename.table_id для автоматического создания UUID первичного ключа при вставке, а затем сохраняет вновь созданный ID в переменную SQL для последующего поиска:

 CREATE TRIGGER `tablename_newid` AFTER INSERT ON `tablename` FOR EACH ROW BEGIN IF ASCII(NEW.table_id) = 0 THEN SET NEW.table_id = UNHEX(REPLACE(UUID(),'-','')); END IF; SET @last_uuid = NEW.table_id; END 

В качестве бонуса он вставляет UUID в двоичной форме в двоичное (16) поле, чтобы сэкономить место для хранения и значительно увеличить скорость запроса.

edit: триггер должен проверить существующее значение столбца, прежде чем вставлять свой собственный UUID, чтобы имитировать возможность предоставления значений для первичных ключей таблицы в MySQL – без этого любые переданные значения всегда будут переопределены триггером. Пример был обновлен, чтобы использовать ASCII() = 0 для проверки наличия значения первичного ключа в INSERT, который будет обнаруживать пустые строковые значения для двоичного поля.

edit 2: после комментария здесь мне было сказано, что использование BEFORE INSERT влияет на настройку переменной @last_uuid даже если сбой строки не выполняется. Я обновил свой ответ, чтобы использовать AFTER INSERT – пока я чувствую, что это совершенно прекрасный подход при общих обстоятельствах, он может иметь проблемы с репликацией строк в кластерных или реплицированных базах данных. Если кто-нибудь знает, я бы тоже хотел!

Чтобы прочитать идентификатор вставки новой строки, просто запустите SELECT @last_uuid .

При запросе и чтении таких двоичных значений функции MySQL HEX() и UNHEX() будут очень полезны, так как будут записывать ваши значения запроса в шестнадцатеричной нотации (которой предшествует 0x ). Код php-side для вашего исходного ответа, учитывая этот тип триггера, примененный к таблице 1, будет:

 // insert row $sql = "INSERT INTO table1(text) VALUES ('some text')"; mysql_query($sql); // get last inserted UUID $sql = "SELECT HEX(@last_uuid)"; $result = mysql_query($sql); $row = mysql_fetch_row($result); $id = $row[0]; // perform a query using said ID mysql_query("SELECT FROM table1 WHERE id = 0x" . $id); 

В ответ на комментарий @ ina :

UUID не является строкой, даже если MySQL предпочитает представлять его как таковой. Это двоичные данные в необработанном виде, и эти тире – это просто дружественный способ MySQL представлять его вам.

Наиболее эффективным хранилищем для UUID является его создание как UNHEX(REPLACE(UUID(),'-','')) – это удалит это форматирование и преобразует его обратно в двоичные данные. Эти функции замедлят первоначальную вставку, но все последующие сравнения, которые вы делаете по этому ключу или столбцу, будут намного быстрее в двоичном поле по 16 байт, чем в 36-символьной строке.

Для одного символьные данные требуют разбора и локализации. Любые строки, поступающие в механизм запроса, обычно сопоставляются автоматически с набором символов базы данных, а некоторые API (WordPress приходит на ум) даже запускают CONVERT() для всех строковых данных перед запросом. Двоичные данные не имеют этих накладных расходов. Для другого ваш char(36) на самом деле выделяет 36 символов , что означает (если ваша база данных UTF-8), каждый символ может составлять 3 или 4 байта в зависимости от используемой вами версии MySQL. Таким образом, char(36) может варьироваться от 36 байт (если он полностью состоит из символов с низким ASCII) до 144, если он состоит исключительно из символов UTF8 высокого порядка. Это намного больше, чем 16 байтов, которые мы выделили для нашего двоичного поля.

Любая логика, выполняемая над этими данными, может быть выполнена с помощью UNHEX() , но лучше выполняется просто сбрасыванием данных в запросах в виде шестнадцатеричных, с префиксом 0x . Это так же быстро, как чтение строки, преобразуется в двоичный код «на лету» и напрямую присваивается соответствующему запросу или ячейке. Очень быстро. Чтение данных немного медленнее – вы должны вызывать HEX() для всех двоичных данных, считываемых из запроса, чтобы получить его в полезном формате, если ваш клиентский API не справляется с бинарными данными (PHP в частном порядке обычно определяет, что бинарные строки === null и будут bin2hex() них, если они будут обработаны без первого вызова bin2hex() , base64_encode() или аналогичного), но эта base64_encode() примерно такая же минимальная, как и сортировка символов и, что более важно, вызывается только на фактические ячейки SELECT ed, не все ячейки, участвующие во внутренних вычислениях результата запроса.

Поэтому, конечно, все эти небольшие увеличения скорости очень минимальны, а в других областях небольшие убытки – но когда вы добавляете их, все binary файлы все же появляются сверху, а когда вы рассматриваете варианты использования и общий принцип «читает» пишет, действительно светит.

… и поэтому binary(16) лучше, чем char(36) .

Его довольно легко на самом деле вы можете передать это mysql, и он вернет вставленный идентификатор.

 set @id=UUID(); insert into <table>(<col1>,<col2>) values (@id,'another value'); select @id; 

В зависимости от того, как реализована функция uuid (), это очень плохая практика программирования – если вы попытаетесь сделать это с включенным двоичным протоколированием (т.е. в кластере), то вставка скорее всего потерпит неудачу . Предложение Ивана показывает, что это может решить ближайшую проблему – однако я думал, что это только возвращает значение, генерируемое для поля с автоматическим приращением, – действительно, это то, что говорится в руководстве .

Также в чем преимущество использования uuid ()? Его вычислительно дорогая генерация, требует большого объема памяти, увеличивает стоимость запроса данных и не криптографически защищена. Вместо этого используйте генератор последовательности или автоинкремент.

Независимо от того, используете ли вы генератор последовательности или uuid, если вы должны использовать это как единственный уникальный ключ в базе данных, тогда вам нужно сначала присвоить значение, прочитать его обратно в phpland и вставить / связать значение как литерал, чтобы последующий запрос на вставку.