1
adoal 2022-03-25 21:35:34 +08:00 1
https://en.wikipedia.org/wiki/Insert_(SQL)#Retrieving_the_key
用子句方式的自然不存在这个问题。用存储过程方式的,是通过数据库内部的实现保存了当前会话里最近一次的数据变更操作结果,而不是再写一条 SQL 到表里去查。注意,你所提到的“self.connection.ops.last_insert_id”实际上是在一个 else:分支里,前面还有 if 和 elif 两个分支,处理的就是用子句方式的情况。 所以其实答案的关键不是 Django 怎么做,而是底层的 SQL 怎么做。这个功能的正确性是 RDBMS 本身保证的。如果某个 RDBMS 不能保证,那 Django 怎么写也没用。 |
2
CEBBCAT 2022-03-25 21:39:56 +08:00 1
楼主对代码的阅读还是有一些偏差,比如“self.connection.ops.last_insert_id”在做的应该不是“select id from user”,我头说起吧,假定你使用的是 MySQL 。
MySQL 提供了 LAST_INSERT_ID() [0]函数,调用它将会返回当前回话上次插入的第一个生成的值,一般就是 AUTO_INCREMENT 。所以 Django 是有能力获取正确的用户 ID 的。而这个函数的运作方式从文档也可以看到,是不受其他 client 影响的,所以不用担心并发。 本来还打了一大堆 InnoDB 、X 锁之类的,重新审题发现好像是我想多了,放在参考资料吧,你再用里面提到的关键词搜索,应该能搜到不少资料。 忘了说,你可以看看 “self.connection.ops.last_insert_id” ,再向下找应该就可以找到 LAST_INSERT_ID() 了。另外虽然我好久没写 Python 了,但 with 显然不是做这个用的。再另外,想问一下楼主是怎么学习 Python 的?感觉基础还需要再扎实一点呀。再另外,我觉得可以把 cursor 理解为一个会话,当然了,最好找专门的文章。 0. https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_last-insert-id 参考资料: https://segmentfault.com/a/1190000023869573 https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html#innodb-insert-intention-locks https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html https://github.com/django/django/blob/379bb201ed346a76e322fe7c6cbd13cb4a6e68a1/django/db/models/sql/compiler.py#L1662-L1666 |
3
xhzhang 2022-03-25 22:08:34 +08:00
with 语句只是一个语法糖,自动打开一个游标,在 with 的代码块内使用完成后,会自动调用 cursor.close()关闭游标。
user = UserModel.objects.create(name="haha") 这句是在数据库写入了一条数据,user 就代表新写入的数据,在 orm 中映射成 User 的一个类实例。只要数据库能保证生产的 id 是正确的,返回类的 id 必然就是正确的。 |
4
chaleaochexist OP @xhzhang 为什么必然是正确的? 如果 orm 是你自己写的, 你如何保证是正确的?
这里是通过两个 sql 实现的功能。 |
5
chaleaochexist OP @CEBBCAT 我问的是 orm 的问题和你说的 MySQL LAST_INSERT_ID()无关。
不过你说的 LAST_INSERT_ID() 这个函数, 确实是对的。 学到了。 |
6
CEBBCAT 2022-03-26 00:00:12 +08:00 via iPhone
@chaleaochexist 无关……无可救药
|
7
CEBBCAT 2022-03-26 00:10:18 +08:00 via iPhone
@CEBBCAT 修正一下,话可能说重了,但你一句话真的是把我憋死了。
ORM 没什么了不起的,无非就是代码多一点的 SQL 生成器,楼上说得很有道理,DBMS 不支持的,ORM 写出花来也没用。 你还是多看看 ORM 代码吧,或者找一些七天 ORM 的博客看看 |
8
chaleaochexist OP @CEBBCAT
@adoal 谢谢 我学到了 刚才理解有误 你们说的都对。我理解错了。 https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-lastrowid.html |