Soru Psycopg2 / Python DB-API ve PostgreSQL ile parametreli sorgular


PostgreSQL'e psycopg2 parametreli sorguları iletmenin en iyi yolu nedir? Kendi escpalama mekanizmalarını veya adaptörlerimi ve psycopg2 kaynak kodunu yazmak istemiyorum ve örnekler bir web tarayıcısında okunması zor.

PyGreSQL veya başka bir python pg adaptörü gibi bir şeye geçmem gerekiyorsa, benimle sorun yok. Sadece basit bir parametreleme istiyorum.


34
2017-09-23 15:28


Menşei


Ne tür bir parametreleme istiyorsun? Sözde kod örneği yararlı olacaktır. - whatnick
Sidenote, SQLAlchemy içine bakmak isteyebilirsiniz, giriş maliyeti, bazı şekillerde biraz daha yüksek olabilir, ama gerçekten çok güzel bir ORM. - Bryan McLemore
Gelecekte referans olması için cevap, dokümanın ilk sayfasındadır: initd.org/psycopg/docs/usage.html - piro
Dokümantasyonda örnekler çok kolaydır. Dinamik değerler için bir güncelleme gibi daha karmaşık bir sorgunun nasıl yapılacağını gösteren hiçbiri yoktur. Gibi bir şey: set height=5, weight=70 - Mutai Mwiti


Cevaplar:


psycopg2 DB-API 2.0 için kuralları takip eder PEP-249). Yani arayabilirsin execute sizin yönteminiz cursor nesne kullan ve kullan pyformat bağlama stili ve sizin için kaçış yapacağız. Örneğin, aşağıdaki meli güvende ol (ve çalış):

cursor.execute("SELECT * FROM student WHERE last_name = %(lname)s", 
               {"lname": "Robert'); DROP TABLE students;--"})

66
2017-09-24 11:47



Yukarıdaki kod da öyle. Tabloyu düşürür müsün? - mascot6699
@ mascot6699 değil, çünkü sorgu parametreli. - Nathan Hinchey


Psycopg belgelerinden

(http://initd.org/psycopg/docs/usage.html)

Uyarı Asla, asla, bir SQL sorgu dizesine değişkenleri iletmek için Python dizgisi birleştirme (+) veya dize parametreleri enterpolasyonunu (%) ASLA kullanmayın. Silah noktasında bile değil.

SQL komutunda değişkenleri geçirmenin doğru yolu, execute () yönteminin ikinci bağımsız değişkenini kullanmaktır:

SQL = "INSERT INTO authors (name) VALUES (%s);" # Note: no quotes

data = ("O'Reilly", )

cur.execute(SQL, data) # Note: no % operator


13
2017-09-23 15:11





İşte size yardımcı olabilecek birkaç örnek

cursor.execute('SELECT * from table where id = %(some_id)d', {'some_id': 1234})

Ya da sorguyu alan adının bir tahmine dayalı olarak dinamik olarak oluşturabilir, değer:

fields = ', '.join(my_dict.keys())
values = ', '.join(['%%(%s)s' % x for x in my_dict])
query = 'INSERT INTO some_table (%s) VALUES (%s)' % (fields, values)
cursor.execute(query, my_dict)

Not: alanların kodunuzda tanımlanması gerekir. değil kullanıcı girişi, aksi takdirde SQL enjeksiyonuna karşı duyarlı olacaksınız.


11
2017-09-23 18:59



Eğer ne yapıyorsun bilemezsen, SQL sorgu olduğundan, sadece sql sorgularına girdi koymalısın. - jb.
SQL enjeksiyona açık bırakmanızı öneri nedeniyle reddedildi - Randy Syring
@RandySyring Bu, tuşlar iyi tanımlanmamış ve uygun tanımlayıcılar değilse sadece SQL enjeksiyonuna açıktır. Değerler hala uygun şekilde parametrelenmiştir. - cpburnz
Yani, genel durumda, size SQL enjeksiyonuna açık bırakır. - rspeer