插入php后获取生成的uuid

Sta*_*tar 7 php mysql uuid

我有一个表字段类型varchar(36),我想通过mysql动态生成它所以我使用此代码:

$sql_code = 'insert into table1 (id, text) values (uuid(),'some text');';
mysql_query($sql_code);
Run Code Online (Sandbox Code Playgroud)

如何在插入记录后立即检索生成的uuid?

zer*_*kms 24

  1. char(36) 更好
  2. 你不能.唯一的解决方案是执行2个独立的查询:

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

其中$ uuid是第一步检索的值.

  • char(36)并不是真的好多了,二元(16)效率最高 (3认同)

pos*_*spi 10

您可以使用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
Run Code Online (Sandbox Code Playgroud)

作为奖励,它将二进制形式的UUID插入二进制(16)字段以节省存储空间并大大提高查询速度.

编辑:触发器应该在插入自己的UUID之前检查现有的列值,以便模仿在MySQL中为表主键提供值的能力 - 如果没有这个,传入的任何值将始终被触发器覆盖.该示例已更新,用于ASCII() = 0检查INSERT中是否存在主键值,该值将检测二进制字段的空字符串值.

编辑2:在这里发表评论之后,我已经向我指出,即使行插入失败,使用也会BEFORE INSERT产生设置@last_uuid变量的效果.我已经更新了我的使用答案AFTER INSERT- 虽然我认为这是一种非常好的方法,但在一般情况下,它可能会在群集或复制数据库下出现行复制问题.如果有人知道,我也会喜欢!

要重新读取新行的插入ID,只需运行即可SELECT @last_uuid.

当查询和阅读这样的二进制值,MySQL的功能HEX()UNHEX()将是非常有益的,这将在16进制(前面加写你的查询值0x).给定应用于table1的这种类型的触发器,原始答案的php端代码将是:

// 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);
Run Code Online (Sandbox Code Playgroud)

跟进@ ina的评论:

UUID不是字符串,即使MySQL选择代表它.它是原始形式的二进制数据,这些破折号只是MySQL友好的代表它的方式.

UUID最有效的存储是将其创建为UNHEX(REPLACE(UUID(),'-',''))- 这将删除该格式并将其转换回二进制数据.这些函数会使原始插入速度变慢,但是对于16字节二进制字段而言,对该键或列进行的所有后续比较将比36字符字符串快得多.

首先,字符数据需要解析和本地化.进入查询引擎的任何字符串通常都会根据数据库的字符集自动进行整理,并且CONVERT()在查询之前甚至会对所有字符串数据运行一些API(wordpress).二进制数据没有这种开销.另一方面,您char(36)实际上分配了36个字符,这意味着(如果您的数据库是UTF-8),每个字符可能长达3或4个字节,具体取决于您使用的MySQL版本.所以a char(36)可以是36字节(如果它完全由低ASCII字符组成)到144(如果完全由高阶UTF8字符组成).这是很多比我们分配给我们的二进制领域的16个字节.

对这些数据执行的任何逻辑都可以完成UNHEX(),但最好只需将查询中的数据转换为十六进制,前缀为0x.这与读取字符串一样快,在运行中转换为二进制并直接分配给相关查询或单元格.非常快.读取数据的速度稍慢 - HEX()如果客户端API不能很好地处理二进制数据,则必须调用从查询中读取的所有二进制数据以使其成为有用的格式(特定的PHP通常会确定二进制字符串=== null和如果在没有第一次调用的情况下进行操作就会破坏它们bin2hex(),base64_encode()或类似的) - 但是这个开销与字符整理一样小,更重要的是仅在实际单元格上调用SELECT,而不是查询结果内部计算中涉及的所有单元格.

所以当然,所有这些小的速度增加都是非常小的,而其他区域导致小的减少 - 但是当你添加它们时binary仍然排在最前面,当你考虑用例和一般的"读取>写入"原则它真的眼前一亮.

......这就是为什么binary(16)比... 好char(36).


ron*_*neo 5

实际上你很容易将它传递给mysql,它将返回插入的id.

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