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)パラメーターは、タプルを1つだけ指定した場合でもリストであるため、最初のargにアクセスするために2つのインデックスが必要であり、次にタプルの列名と値にアクセスするために0または1が必要でした。
.fetchall()自体は、レコードが見つかった場合にカーソルからデータをクリアするため、「未読レコード」エラーを防ぐために必要でした。