Saya memiliki objek kueri SQLAlchemy dan ingin mendapatkan teks dari pernyataan SQL yang dikompilasi, dengan semua parameternya terikat (misalnya tidak ada %s
atau variabel lain yang menunggu untuk diikat oleh penyusun pernyataan atau mesin dialek MySQLdb, dll).
Memanggil str()
kueri akan mengungkapkan sesuatu seperti ini:
SELECT id WHERE date_added <= %s AND date_added >= %s ORDER BY count DESC
Saya sudah mencoba mencari di query._params tetapi itu adalah dikt yang kosong. Saya menulis kompiler saya sendiri menggunakan contoh sqlalchemy.ext.compiler.compiles
dekorator ini tetapi bahkan pernyataan di sana masih memiliki %s
tempat yang saya inginkan datanya.
Saya tidak tahu kapan parameter saya dicampur untuk membuat kueri; saat memeriksa objek kueri, mereka selalu berupa kamus kosong (meskipun kueri dijalankan dengan baik dan mesin mencetaknya saat Anda mengaktifkan log gema).
Saya mulai mendapatkan pesan bahwa SQLAlchemy tidak ingin saya mengetahui kueri yang mendasarinya, karena hal itu merusak sifat umum antarmuka API ekspresi semua DB-API yang berbeda. Saya tidak keberatan jika kueri dieksekusi sebelum saya menemukan apa itu; Saya hanya ingin tahu!
sumber
c = q.statement.compile(...)
, Anda bisa mendapatkanc.params
as_scalar()
-method ofQuery
.str(q)
.The dokumentasi menggunakan
literal_binds
untuk mencetak queryq
termasuk parameter:Dokumentasi juga mengeluarkan peringatan ini:
sumber
Ini harus bekerja dengan Sqlalchemy> = 0.6
sumber
adapt
dengan cara ini. Minimal panggil prepared () pada nilai kembalian darinya setiap kali, menyediakan koneksi sebagai argumen, sehingga bisa melakukan kutipan yang tepat.prepare
pada nilai balik tapi tampaknya itu tidak memiliki metode yang:AttributeError: 'psycopg2._psycopg.AsIs' object has no attribute 'prepare'
. Saya menggunakan psycopg2 2.2.1 BTWUntuk backend MySQLdb saya memodifikasi jawaban albertov yang luar biasa (terima kasih banyak!) Sedikit. Saya yakin mereka dapat digabungkan untuk memeriksa apakah
comp.positional
adaTrue
tetapi itu sedikit di luar cakupan pertanyaan ini.sumber
return tuple(params)
berfungsi seperti pesona! Anda menyelamatkan saya berjam-jam karena harus melalui jalan yang sangat menyakitkan.Masalahnya, sqlalchemy tidak pernah mencampur data dengan kueri Anda. Kueri dan data diteruskan secara terpisah ke driver database yang mendasarinya - interpolasi data terjadi di database Anda.
Sqlalchemy meneruskan kueri seperti yang Anda lihat di
str(myquery)
database, dan nilainya akan ditempatkan dalam tupel terpisah.Anda dapat menggunakan beberapa pendekatan di mana Anda menginterpolasi data dengan kueri sendiri (seperti yang disarankan albertov di bawah), tetapi itu bukan hal yang sama yang dijalankan oleh sqlalchemy.
sumber
SELECT id WHERE date_added <= %s AND date_added >= %s ORDER BY count DESC
ADALAH pertanyaan terakhir. Itu%s
dikirim ke database oleh sqlalchemy - sqlalchemy PERNAH menempatkan data aktual di tempat% ssqlalchemy.dialects.mysql.mysqldb
,do_executemany()
meneruskan pernyataan & parameter secara terpisah ke kursor MySQLdb. yay tipuan!Pertama izinkan saya memberi pengantar dengan mengatakan bahwa saya berasumsi Anda melakukan ini terutama untuk tujuan debugging - Saya tidak akan merekomendasikan mencoba mengubah pernyataan di luar SQLAlchemy fluent API.
Sayangnya, tampaknya tidak ada cara sederhana untuk menampilkan pernyataan yang dikompilasi dengan parameter kueri yang disertakan. SQLAlchemy sebenarnya tidak memasukkan parameter ke dalam pernyataan - mereka diteruskan ke mesin database sebagai kamus . Ini memungkinkan pustaka khusus database menangani hal-hal seperti keluar dari karakter khusus untuk menghindari injeksi SQL.
Tetapi Anda dapat melakukan ini dalam proses dua langkah dengan cukup mudah. Untuk mendapatkan pernyataan tersebut, Anda dapat melakukan seperti yang telah Anda tunjukkan, dan cukup mencetak kueri:
Anda bisa selangkah lebih dekat dengan query.statement, untuk melihat nama parameter. Catatan di
:id_1
bawah vs di%s
atas - sebenarnya bukan masalah dalam contoh yang sangat sederhana ini, tetapi bisa menjadi kunci dalam pernyataan yang lebih rumit.Kemudian, Anda bisa mendapatkan nilai parameter yang sebenarnya dengan mendapatkan
params
properti dari pernyataan yang dikompilasi:Ini bekerja setidaknya untuk backend MySQL; Saya berharap ini juga cukup umum untuk PostgreSQL tanpa perlu digunakan
psycopg2
.sumber
Untuk backend postgresql menggunakan psycopg2, Anda dapat mendengarkan
do_execute
acara, kemudian menggunakan cursor, pernyataan, dan ketik parameter yang dipaksa bersama denganCursor.mogrify()
untuk menyebariskan parameter. Anda dapat mengembalikan True untuk mencegah eksekusi kueri yang sebenarnya.Penggunaan sampel:
sumber
Solusi berikut menggunakan SQLAlchemy Expression Language dan bekerja dengan SQLAlchemy 1.1. Solusi ini tidak mencampur parameter dengan kueri (seperti yang diminta oleh penulis asli), tetapi menyediakan cara menggunakan model SQLAlchemy untuk menghasilkan string kueri SQL dan kamus parameter untuk dialek SQL yang berbeda. Contohnya berdasarkan tutorial http://docs.sqlalchemy.org/en/rel_1_0/core/tutorial.html
Mengingat kelasnya,
kami dapat menghasilkan pernyataan kueri menggunakan fungsi pilih .
Selanjutnya, kita dapat mengompilasi pernyataan tersebut menjadi objek kueri.
Secara default, pernyataan dikompilasi menggunakan implementasi 'bernama' dasar yang kompatibel dengan database SQL seperti SQLite dan Oracle. Jika Anda perlu menentukan dialek seperti PostgreSQL, Anda bisa melakukannya
Atau jika Anda ingin secara eksplisit menetapkan dialek sebagai SQLite, Anda dapat mengubah paramstyle dari 'qmark' menjadi 'bernama'.
Dari objek query, kita dapat mengekstrak string query dan parameter query
dan terakhir jalankan kueri.
sumber
Anda dapat menggunakan acara dari keluarga ConnectionEvents :
after_cursor_execute
ataubefore_cursor_execute
.Dalam sqlalchemy UsageRecipes oleh @zzzeek Anda dapat menemukan contoh ini:
Di sini Anda bisa mendapatkan akses ke pernyataan Anda
sumber
Jadi, mengumpulkan banyak potongan kecil dari jawaban yang berbeda ini, saya menemukan apa yang saya butuhkan: satu set kode sederhana untuk dimasukkan dan kadang-kadang tetapi dapat diandalkan (yaitu menangani semua tipe data) ambil SQL terkompilasi yang tepat yang dikirim ke my Postgres backend dengan hanya menginterogasi kueri itu sendiri:
sumber
Saya pikir .statement mungkin akan berhasil: http://docs.sqlalchemy.org/en/latest/orm/query.html?highlight=query
sumber