如何插入一个匹配的MySQL行已经不存在了

时间:2012-04-13 15:26:32

标签: python mysql insert mysql-python

我的表bank有三列:uid,nick和balance。

我可以完美地插入新行,但是nickuid自动增量后,nick的副本很容易出现,使每一行都是唯一的。但是我不希望这样,我只想为每个 target = input.group(2) cursor.execute ("INSERT INTO bank (nick, balance) VALUES('" + db.escape_string(target.lower()) + "', 5)") db.commit() bot.say('An account for ' + target + ' has been created.') 想要一行。

SELECT

到目前为止,这是我的代码,但我不确定如何创建nick查询,然后在插入新行之前检查表中是否已存在{{1}}。

4 个答案:

答案 0 :(得分:3)

我会采用不同的方法。我会在nick列的数据库级别添加唯一约束:

ALTER TABLE bank ADD UNIQUE (nick);

在您的Python代码中,然后添加tryexcept以适当地处理唯一约束违反异常。

答案 1 :(得分:0)

听起来没有那种增量ID的意义 相反,请考虑帐户的唯一标识符,例如一个帐号。
另一个答案表明,在nick添加唯一约束的危险在于,随着人口的增长,您可能会有两个或更多人希望使用相同的nick

此外,您应该将值作为第二个参数传递给execute(),原因至少有两个原因*。

cursor.execute("""INSERT INTO bank (nick, balance) 
                  VALUES (%s, %s);""", (target.lower(), 5))

*有两个原因:

  1. 您可以避免手动处理任何引用问题。 Mysql-Python将为您解决这个问题。
  2. 您可以避免SQL注入攻击的可能性。
  3. 请注意:参数占位符对于所有类型的参数都是%s,而不仅仅是字符串。因此,需要执行%d之类的操作来插入整数。

答案 2 :(得分:0)

我想你正在使用psycopg2

cursor.execute(“SELECT * FROM bank WHERE nick =%s”,[nick])

nick = cursor.fetchall()

如果尼克......

答案 3 :(得分:0)

我正在使用Python(3.6)和MySql,我想在添加记录之前检查记录。 这是我的代码:

Autowired

此函数采用表名,列名列表,要插入的值列表以及可选的元组(如果您以此方式提供自己的索引)

import mysql.connector

mydb = mysql.connector.connect(
  host="localhost",
  user="user",
  passwd="password",
  database='football'
)

mycursor = mydb.cursor()

def write_to_db(db_table, col_list, data_list, *supply_id):
    """
    Takes a record, checks if it already exists and if not inserts it, returning its index or None
    :param db_table: name of table to be checked / inserted into
    :param col_list: column/field names in a list eg.  ['meat', 'sides']
    :param data_list: data to be found or inserted eg ['spam', 'eggs']
    :param supply_id: Only if you supply calculated id as tuple ('table_id', table_id_val)
    :return: If lists don't match =None Else =Index of found record or Index of inserted one
    """
    if len(col_list) != len(data_list) or len(col_list) == 0: # List lengths must match
        return None     # Otherwise returned index is None
    # Build search SQL - Select - table - Where - match conditions
    find_existing_sql = 'SELECT * FROM {} '.format(db_table)    # Which table
    find_existing_sql += 'WHERE {} = {} '.format(col_list[0], data_list[0])
    sql_end = ' LIMIT 1 ;'
    if len(col_list) > 1:  # Provided record has more than 1 column
        and_sql = ' AND {} = {} '           # add extra match condition for each column
        for indx in list(range(1, len(col_list))):
            find_existing_sql += and_sql.format(col_list[indx], data_list[indx])
        find_existing_sql += sql_end        # Complete SQL to find given record
    my_cursor.execute(find_existing_sql)    # Query database with SQL
    seek_response = my_cursor.fetchall()    # Read the seek a record response
    record_exists = len(seek_response) > 0  # Length = 0 not found, > 0 found
    if record_exists:
        return seek_response[0][0]          # Return id = the first item from the first list of items
    else:
        # Build insert SQL - Insert into  - table - column names - values 
        insert_sql = 'INSERT INTO {} ('.format(db_table)    # Which table
        if supply_id is not None:       # If you supplied an index
            id_col = supply_id[0][0]    # first item in first arg = index name
            id_val = supply_id[0][1]    # second item in first arg = index value
            col_list =[id_col] + col_list       # Add index column name on the front of column list
            data_list = [id_val] + data_list    # Add index value on front of data_list
        first_col = '{}'.format(col_list[0])    # Start listing columns
        more_cols_vals = ', {}'                 # To add more coumns/values if needed
        values_sql = ') VALUES ( {} '.format(data_list[0]) # Start listing values
        end_sql = ' );'  
        insert_cols_sql = insert_sql + first_col    
        if len(col_list) > 1:       
            for indx in list(range(1, len(col_list))):
                insert_cols_sql += more_cols_vals.format(col_list[indx])
                values_sql += more_cols_vals.format(data_list[indx])
        # Put Insert SQL together
        insert_new_sql = insert_cols_sql + values_sql + end_sql
        my_cursor.execute(insert_new_sql) # Insert the new record into db
        mydb.commit()
        if supply_id is not None:   # If you supplied an index
            return id_val           # Return that
        else:                           # if not
            return my_cursor.lastrowid  # Return auto-generated index

但是如果您不提供该元组,MySQL将使用自动生成的索引进行插入。 该例程假定您的表的第一列为索引。

它返回找到的记录的索引(如果已存在),如果该记录不存在,则返回插入记录时使用的索引。该索引可以是MySQL生成的索引,也可以是您提供的索引。 如果您的列名列表和值列表的长度不匹配,则返回None。

我已经使用Python构建了SQL语句,因此您可以拥有可变数量的列。 您可以在SQL中传递值(尽管我不知道如何对可变数量的列和值执行此操作),但是我一直遇到“参数数量错误”错误,并使用Python的string.format()解决了该问题。

即使您只提供一个元组,* supply_id(通常为* args)参数也是一个列表,因此我需要两个索引来访问第一个arg,然后需要0或1来访问元组中的列名和值。 / p>

.fetchall()本身对于防止“未读记录”错误是必要的,因为如果找到记录,它将清除游标中的数据。