1

私のテーブルbankには、uid、nick、balanceの3つの列があります。

新しい行を完全にうまく挿入できますnickが、自動インクリメントされるため、の重複が簡単に表示され、uid各行が一意になります。しかし、私はそれを望んでいません。私はそれぞれに1つの行だけが必要です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、新しい行を挿入する前にテーブルにすでに存在するかどうかを確認する方法がわかりません。

4

4 に答える 4

3

私は別のアプローチを採用します。列にDBレベルで一意の制約を追加します。nick

ALTER TABLE bank ADD UNIQUE (nick);

Pythonコード内に、tryとを配置して、一意の制約違反の例外を適切exceptに処理します。

于 2012-04-13T15:38:34.390 に答える
0

その増分IDを持つことは意味がないように聞こえます。
代わりに、アカウントの一意の識別子(アカウント番号など)を検討してください。
別の回答が示唆するように、に一意性制約を追加することの危険性はnick、人口が増えるにつれて、同じものを使用したい2人以上の人がいる可能性が高いことですnick

execute()また、少なくとも2つの理由で、2番目の引数として挿入する値を渡す必要があります*。

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

*その2つの理由は次のとおりです。

  1. 見積もりの​​問題を手動で処理する必要がなくなります。Mysql-Pythonがそれを処理します。
  2. SQLインジェクション攻撃の可能性を回避します。

注意:パラメータのプレースホルダーは%s、文字列だけでなく、すべてのタイプのパラメータに対応しています。したがって、整数を挿入するようなことをする必要はありません。%d

于 2012-04-13T15:36:03.297 に答える
0

psycopg2を使用していると思います

cursor.execute( "SELECT * FROM bank WHERE nick =%s"、[nick])

ニック=cursor.fetchall()

ニックの場合..。

于 2012-04-13T15:37:45.373 に答える
0

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()自体は、レコードが見つかった場合にカーソルからデータをクリアするため、「未読レコード」エラーを防ぐために必要でした。

于 2019-01-22T10:24:58.400 に答える