Python 如果匹配的MySQL行不存在,如何插入该行
我的表Python 如果匹配的MySQL行不存在,如何插入该行,python,mysql,insert,mysql-python,Python,Mysql,Insert,Mysql Python,我的表bank有三列:uid、nick和balance 我可以很好地插入新行,但是很容易出现重复的nick,因为uid自动递增,使每一行都是唯一的。但是我不希望这样,我只希望每个nick有一行 target = input.group(2) cursor.execute ("INSERT INTO bank (nick, balance) VALUES('" + db.escape_string(target.lower()) + "', 5)") db.commit(
bank
有三列:uid、nick和balance
我可以很好地插入新行,但是很容易出现重复的nick
,因为uid
自动递增,使每一行都是唯一的。但是我不希望这样,我只希望每个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.')
到目前为止,这是我的代码,但是我不确定如何创建一个
选择
查询,然后在插入新行之前检查表中是否已经存在尼克
。使用该递增ID听起来没有意义。而是考虑帐户的唯一标识符,例如帐号。 另一个答案表明,在
nick
上添加一个独特的约束的危险在于,随着人口的增长,可能会有两个或两个以上的人希望使用相同的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.')
此外,您应该将要插入的值作为第二个参数传递给execute()
,至少有两个原因*
cursor.execute("""INSERT INTO bank (nick, balance)
VALUES (%s, %s);""", (target.lower(), 5))
*原因有两个:
请注意:对于所有类型的参数,而不仅仅是字符串,参数占位符是
%s
。因此,您不需要像插入整数那样执行任何操作。我想您使用的是psycopg2
cursor.execute(“从nick=%s的银行选择*,[nick])
nick=cursor.fetchall()
如果尼克…我会采取不同的方法。我会在
nick
列的DB级别添加一个唯一的约束:
ALTER TABLE bank ADD UNIQUE (nick);
在Python代码中,然后放置一个try
和except
,以适当地处理违反唯一约束的异常。我正在使用Python(3.6)和MySql,我想在添加记录之前检查记录。
这是我的密码:
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
如果您提供自己生成的索引,此函数将获取表名、列名列表、要插入的值列表和可选元组
('table_id', table_id_value)
但是如果不提供这个元组,MySQL将使用自动生成的索引进行插入。
该例程假定表的第一列是索引
如果找到的记录已经存在,则返回该记录的索引;如果该记录不存在,则返回插入该记录时使用的索引。索引可以是MySQL生成的索引,也可以是您提供的索引。
如果列名列表和值列表长度不匹配,则返回None
我已经使用Python构建了SQL语句,因此您可以拥有可变数量的列。
您可以在SQL中传递值(虽然我不知道如何对数量可变的列和值传递值),但我一直遇到“参数数量错误”的错误,并使用Python的string.format()解决了这一问题
即使只提供一个元组,*supply_id(通常是*args)参数也是一个列表,因此我需要两个索引来访问第一个参数,然后是0或1来访问元组中的列名和值
.fetchall()本身对于防止“未读记录”错误是必需的,因为如果找到记录,它会从游标中清除数据
uid
基本上是我唯一标识帐户的方式,这就是为什么我设置它为每个新帐户添加一个。谢谢你的提示,我会的。但我仍然无法解决原来的问题。那么,这些账户是如何重复的呢?两个账户不能有相同的缺口
和余额
?这似乎是一种任意的限制……新帐户仍然可以使用相同的nick
一次又一次地添加,而uid
只会不断增加。您的问题现在似乎与问题中所写的略有不同……根据应用程序逻辑,您可能还希望在INSERT中添加一个on REPLICATE KEY子句,而不是处理异常。@liquorvicar Yes,具体取决于应用程序逻辑。就个人而言,越是“行为”逻辑,它就越适合Python(而不是SQL)。在这种情况下,UNIQUE
约束是DDL
,本身不是“行为”。然而,这只是我个人的喜好。我对这个独特的有点困惑,查询如何知道nick
值是什么?“我试着搜索,但这一切对我来说似乎有点太混乱了。@Markum解释UNIQUE
约束。基本上,如果您的代码尝试插入一个已经存在的nick
值,那么约束将被违反,并且Python代码中会出现异常,您可以像往常一样通过try
和except
来实现。