mysql插入数据,获取最新插入的ID(自增列)的思路和python获取MySQL自增ID代码三种实现

mysql本身有一个列可以做自增长字段,mysql在插入一条数据后,如何能获得到这个自增id的值呢?

(1)方法一 是使用last_insert_id

mysql> SELECT LAST_INSERT_ID();

产生的ID 每次连接后保存在服务器中。这意味着函数向一个给定客户端返回的值是该客户端产生对影响AUTO_INCREMENT列的最新语句第一个 AUTO_INCREMENT值的。这个值不能被其它客户端影响,即使它们产生它们自己的 AUTO_INCREMENT值。这个行为保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁或处理。 

每次mysql_query操作在mysql服务器上可以理解为一次“原子”操作, 写操作常常需要锁表的, 是mysql应用服务器锁表不是我们的应用程序锁表。

值得注意的是,如果你一次插入了多条记录,这个函数返回的是第一个记录的ID值。

因为LAST_INSERT_ID是基于Connection的,只要每个线程都使用独立的Connection对象,LAST_INSERT_ID函数将返回该Connection对AUTO_INCREMENT列最新的insert or update*作生成的第一个record的ID。这个值不能被其它客户端(Connection)影响,保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁。使用单INSERT语句插入多条记录, LAST_INSERT_ID返回一个列表。

LAST_INSERT_ID 是与table无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID会改变。

(2)方法二是使用max(id)

使用last_insert_id是基础连接的,如果换一个窗口的时候调用则会一直返回10

如果不是频繁的插入我们也可以使用这种方法来获取返回的id值

select max(id) from stu_info;

这个方法的缺点是不适合高并发。如果同时插入的时候返回的值可能不准确。

在MySQL中,使用auto_increment类型的id字段作为表的主键。通常的做法,是通过“select max(id) from tablename”的做法,但是显然这种做法需要考虑并发的情况,需要在事务中对主表以“X锁“,待获得max(id)的值以后,再解锁。  

这种做法需要的步骤比较多,有些麻烦,而且并发性也不好。有没有更简单的做法呢?答案之一是通过select LAST_INSERT_ID()这个操作。乍一看,它和select max(id)很象,但实际上它是线程安全的。也就是说它是基于数据库连接的,基于数据库连接是什么意义呢?举例说明:  

   1)、在连接1中向A表插入一条记录,A表包含一个auto_increment类型的id。

   2)、在连接2中向A表再插入一条记录。

   3)、结果:在连接1中执行select LAST_INSERT_ID()得到的结果和连接2中执行select LAST_INSERT_ID()的结果是不同的;而在两个连接中执行select max(id)的结果是相同的。

(4)python获取MySQL自增ID代码三种实现:

Python通过MySQLdb向MySQL读写数据,如果表中含有自增主键,想要获取本次插入数据的ID代码如下:

# -*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
import MySQLdb
import json
class Mysql():
    def return_id(self):
        conn = MySQLdb.connect(host=self.__my_host, user=self.__my_user, passwd=self.__my_passwd,
                               db=self.__my_db, port=int(self.__my_port), charset=self.__my_charset)
        cursor = conn.cursor()

        # 代码块A
        user_id = 10010
        name = "Tom"
        sql_insert = "insert spark_db.stu_info(user_id,name) values ('%s','%s')" % (str(user_id), str(name))
        rs = cursor.execute(sql_insert)

        # # 代码块B
        # sql_update = "update spark_db.stu_info set  name ='%s',user_id= '%s' where id = 40 " % (str('张三'),str(2000) )
        # rs = cursor.execute(sql_update)

        print "此次操作影响的行数为: rs", rs  # 此次插入操作影响的行数

        # 方法一,使用insert_id()方法:  插入一条记录后,获取这条数据所在的自增ID
        print "使用insert_id()函数 ",
        print "conn.insert_id()", conn.insert_id()
        conn.commit()

        # 方法二,使用LAST_INSERT_ID()方法: 插入一条记录后,获取这条数据所在的自增ID
        print "使用LAST_INSERT_ID()函数 ",
        sql = ''' select LAST_INSERT_ID() '''
        num = cursor.execute(sql)
        if num>0:
            print cursor.fetchall()
        # 方法三,使用max()方法: 插入一条记录后,获取这条数据所在的自增ID
        sql = ''' select max(id) from spark_db.stu_info'''
        print "使用max()函数 ",
        num = cursor.execute(sql)
        if num > 0:
            print cursor.fetchall()

def test_main():
    with open("./config/mysql.json", "r") as f:
        config_json = json.loads(f.read())
    print "config_json\n", config_json
    mysql_client = Mysql(in_config_json=config_json['titan_db'])
    print "\n数据插入之前\n"
    num=mysql_client.execute_db("select * from spark_db.stu_info ")
    if num>0:
        print mysql_client.fetchall_db()
    print "\n数据插入操作\n"

    mysql_client.return_id()

    print "\n数据插入后\n"
    num = mysql_client.execute_db("select * from spark_db.stu_info ")
    if num > 0:
        print mysql_client.fetchall_db()
if __name__ == '__main__':
    test_main()

 

代码块A的输出结果如下:

数据插入之前

({'user_id': 10010L, 'id': 27L, 'name': u'Tom'},)

数据插入操作

此次操作影响的行数为: rs 1
使用insert_id()函数  conn.insert_id() 29
使用LAST_INSERT_ID()函数  ((29L,),)
使用max()函数  ((29L,),)

数据插入后

({'user_id': 10010L, 'id': 27L, 'name': u'Tom'}, {'user_id': 10010L, 'id': 29L, 'name': u'Tom'}) 

代码块B的输出结果如下:

数据插入操作

此次操作影响的行数为: rs 0
使用insert_id()函数  conn.insert_id() 0
使用LAST_INSERT_ID()函数  ((0L,),)
使用max()函数  ((41L,),)

所有返回自增ID只能是insert操作,而不是update操作

参考:https://blog.csdn.net/anan890624/article/details/50808515

Logo

更多推荐