Bagaimana cara menggunakan variabel dalam pernyataan SQL dengan Python?


94

Ok jadi saya tidak begitu berpengalaman dengan Python.

Saya memiliki kode Python berikut:

cursor.execute("INSERT INTO table VALUES var1, var2, var3,")

Dimana var1adalah integer, var2& var3adalah string.

Bagaimana saya bisa menulis nama variabel tanpa python memasukkannya sebagai bagian dari teks kueri?

Jawaban:


107
cursor.execute("INSERT INTO table VALUES (%s, %s, %s)", (var1, var2, var3))

Perhatikan bahwa parameter dikirimkan sebagai tupel.

API database melakukan pelolosan dan kutipan variabel dengan benar. Berhati-hatilah untuk tidak menggunakan operator pemformatan string ( %), karena

  1. ia tidak melakukan pelolosan atau kutipan.
  2. itu rentan terhadap serangan format string yang tidak terkontrol misalnya injeksi SQL .

Menarik, mengapa ini bekerja dengan vars secara terpisah dan bukan dalam array (var1, var2, var3)?
— Andomar

Menurut spesifikasi DB API, sepertinya itu bisa terjadi: python.org/dev/peps/pep-0249
— Ayman Hourieh

9
@thekashyap Baca lagi dengan seksama. Apa yang tidak aman menggunakan operator pemformatan string %. Nyatanya, saya katakan demikian dalam jawabannya.
— Ayman Hourieh

saya buruk .. Saya membayangkan % alih- ,alih antara string dan variabel .. tidak dapat membatalkan suara saya karena berbagai alasan .. Saya pribadi ingin melihat kata-kata seperti tidak aman / serangan dll disebutkan dalam deskripsi di mana Anda mengatakan jangan tidak digunakan %..
— Kashyap

1
@eric jawabannya mengatakan jangan gunakan % operator untuk memformat string. Mereka yang ada %dalam string digunakan cursor.executesecara langsung, dan karena ia tahu itu menghasilkan SQL, ia dapat berbuat lebih banyak untuk melindungi Anda.
— Mark Ransom

69

Implementasi berbeda dari Python DB-API diizinkan untuk menggunakan placeholder yang berbeda, jadi Anda harus mencari tahu mana yang Anda gunakan - bisa juga (misalnya dengan MySQLdb):

cursor.execute("INSERT INTO table VALUES (%s, %s, %s)", (var1, var2, var3))

atau (misalnya dengan sqlite3 dari pustaka standar Python):

cursor.execute("INSERT INTO table VALUES (?, ?, ?)", (var1, var2, var3))

atau yang lain (setelah VALUESAnda bisa memiliki (:1, :2, :3), atau "gaya bernama" (:fee, :fie, :fo)atau di (%(fee)s, %(fie)s, %(fo)s)mana Anda meneruskan dict alih-alih peta sebagai argumen kedua ke execute). Periksa paramstylekonstanta string dalam modul DB API yang Anda gunakan, dan cari paramstyle di http://www.python.org/dev/peps/pep-0249/ untuk melihat apa saja gaya parameter-passing itu!


Apakah mungkin untuk melakukan hal yang sama tetapi dengan skrip SQL eksternal?
— Novitoll

49

Banyak jalan. JANGAN gunakan yang paling jelas ( %sdengan %) dalam kode nyata, itu terbuka untuk serangan .

Di sini salin-tempel dari pydoc dari sqlite3 :

# Never do this -- insecure!
symbol = 'RHAT'
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)

# Do this instead
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
print c.fetchone()

# Larger example that inserts many records at a time
purchases = [('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
             ('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
             ('2006-04-06', 'SELL', 'IBM', 500, 53.00),
            ]
c.executemany('INSERT INTO stocks VALUES (?,?,?,?,?)', purchases)

Lebih banyak contoh jika Anda membutuhkan:

# Multiple values single statement/execution
c.execute('SELECT * FROM stocks WHERE symbol=? OR symbol=?', ('RHAT', 'MSO'))
print c.fetchall()
c.execute('SELECT * FROM stocks WHERE symbol IN (?, ?)', ('RHAT', 'MSO'))
print c.fetchall()
# This also works, though ones above are better as a habit as it's inline with syntax of executemany().. but your choice.
c.execute('SELECT * FROM stocks WHERE symbol=? OR symbol=?', 'RHAT', 'MSO')
print c.fetchall()
# Insert a single item
c.execute('INSERT INTO stocks VALUES (?,?,?,?,?)', ('2006-03-28', 'BUY', 'IBM', 1000, 45.00))

4
Beberapa implementasi DB-API sebenarnya menggunakan% s untuk variabel mereka - terutama psycopg2 untuk PostgreSQL. Hal ini tidak menjadi bingung (meskipun mudah) dengan menggunakan% s dengan operator% untuk penggantian string. Saya akan sangat baik jika, untuk portabilitas, kita bisa saja memiliki cara standar yang ditentukan untuk menentukan parameter SQL untuk DB-API.
— ThatAintWorking

26

http://www.amk.ca/python/writing/DB-API.html

Berhati-hatilah saat Anda menambahkan nilai variabel ke pernyataan Anda: Bayangkan pengguna menamai dirinya sendiri ';DROP TABLE Users;'- Itulah mengapa Anda perlu menggunakan sql escaping, yang disediakan Python untuk Anda saat Anda menggunakan cursor.execute dengan cara yang layak. Contoh di url adalah:

cursor.execute("insert into Attendees values (?, ?, ?)", (name,
seminar, paid) )

13
Sebenarnya, ini bukan SQL escaping. Ini mengikat variabel, yang jauh lebih sederhana dan lebih langsung. Nilai terikat ke dalam pernyataan SQL setelah parsing, membuatnya kebal terhadap serangan injeksi apa pun.
— S. Lott

baik, apakah itu SQL escaping atau variable binding tergantung pada seberapa baik atau buruk server database / driver DB-API Anda. Saya telah melihat beberapa database produksi dunia nyata dan tersebar luas yang memiliki driver DB-API mereka yang melarikan diri, daripada menyimpan data dan kode di luar jalur kabel. Tak perlu dikatakan, saya tidak terlalu menghormati yang disebut "database".
— Charles Duffy
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.