Frage

Aus irgendwelchen Gründen, würde Ich mag ein expliziten tun zitiert aus einem String-Wert (einen Teil konstruiert SQL-Abfrage zu werden) statt durch cursor.execute Verfahren auf Inhalt seines zweiten Parameters durchgeführt für implizites Zitat warten.

Mit dem "impliziten Zitat" Ich meine:

value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;"
cursor.execute( query, (value,) ) # value will be correctly quoted

Ich würde so etwas bevorzugen:

value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;" % \
    READY_TO_USE_QUOTING_FUNCTION(value)
cursor.execute( query ) # value will be correctly quoted, too

Ist solch niedrigen Niveau READY_TO_USE_QUOTING_FUNCTION erwartet von Python DB-API-Spezifikation (I nicht eine solche Funktionalität in PEP 249 Dokument). Wenn nicht, bietet vielleicht psycopg2 solche Funktion? Wenn nicht, vielleicht bietet Django solche Funktion? Ich würde es vorziehen, nicht solche Funktion selbst ...

schreiben
War es hilfreich?

Lösung

Ok, so war ich neugierig und ging hin und sah die Quelle psycopg2. Stellt sich heraus, ich habe nicht weiter zu gehen als die Beispiele Ordner:)

Und ja, das ist psycopg2 spezifisch. Grundsätzlich, wenn Sie nur wollen, um eine Zeichenfolge zitieren Sie das tun würden:

from psycopg2.extensions import adapt

print adapt("Hello World'; DROP DATABASE World;")

Aber was wollen Sie wahrscheinlich zu tun ist, Ihren eigenen Adapter zu schreiben und registrieren;

In den Beispielen Ordner psycopg2 Sie die Datei finden 'myfirstrecipe.py' gibt es ein Beispiel dafür, wie eine bestimmte Art in besonderer Weise zu werfen und zu zitieren.

Wenn Sie Objekte für das Zeug haben Sie tun möchten, können Sie einfach einen Adapter erstellen, die auf die ‚IPsycopgSQLQuote‘ Protokoll entspricht (siehe pydocs für das myfirstrecipe.py-Beispiel ... eigentlich ist, dass der einzige Hinweis, den ich finden kann zu diesem Namen), die Ihr Objekt zitiert und Registrierung es dann etwa so:

from psycopg2.extensions import register_adapter

register_adapter(mytype, myadapter)

Auch die anderen Beispiele interessant; esp. 'dialtone.py' und 'simple.py' .

Andere Tipps

Ich glaube, Sie suchen die mogrify Funktion.

Beispiel:

>>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
"INSERT INTO test (num, data) VALUES (42, E'bar')"

Sie sollten versuchen, Ihre eigenen zu tun zu vermeiden zitieren. Nicht nur wird es DB-spezifisch sein, wie die Menschen aus haben darauf, dass jedoch die Probleme zu zitieren sind die Quelle der SQL-Injection-Fehler.

Wenn Sie nicht separat um Abfragen und Werte übergeben wollen, dann passiert um eine Liste der Parameter:

def make_my_query():
    # ...
    return sql, (value1, value2)

def do_it():
    query = make_my_query()
    cursor.execute(*query)

(Ich habe wahrscheinlich die Syntax von cursor.execute falsch) Der Punkt hier ist, dass nur weil cursor.execute eine Reihe von Argumenten nimmt, die nicht Sie bedeutet haben sie alle einzeln zu behandeln. Sie können mit ihnen als eine Liste behandeln.

Ich glaube nicht, dass Sie jede ausreichende Gründe für Ihre Vermeidung geben dies der richtige Weg zu tun. Bitte verwenden Sie die APi wie es konzipiert ist und versuchen Sie nicht so hart, um Ihren Code weniger lesbar für den nächsten Mann und zerbrechlicher zu machen.

Das wird sein DB abhängig. Im Fall von MySQLdb zum Beispiel der connection Klasse eine literal Methode, die den Wert auf die richtige entkam Darstellung für das Bestehen zu MySQL konvertiert (das ist, was cursor.execute verwendet).

Ich stelle mir vor Postgres etwas ähnliches hat, aber ich glaube nicht, dass es eine Funktion Werte als Teil des DB-API 2.0-Spezifikation zu entkommen.

sein Das wird Datenbank abhängig (IIRC, mysql erlaubt \ als Escape-Zeichen, während so etwas wie Orakel Anführungszeichen erwartet verdoppelt werden: 'my '' quoted string').

Jemand korrigieren Sie mich, wenn ich falsch bin, aber die Doppel zitierte Methode ist die Standardmethode.

Es kann zu welcher anderen db Abstraktion Bibliotheken tun (sqlalchemy, cx_Oracle, SQLite, etc) auf der Suche wert sein.

Ich habe zu fragen, bekam - warum wollen Sie die Werte inline statt sie binden

Ihr Code-Snippet erhalten würde, genau wie dieser, nach psycopg Erweiterung docs

from psycopg2.extensions import adapt

value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;" % \
    adapt(value).getquoted()
cursor.execute( query ) # value will be correctly quoted, too

Die getquoted Funktion gibt den value als zitiert und maskierten String so könnten Sie auch gehen. "SELECT * FROM some_table WHERE some_char_field = " + adapt(value).getquoted()

PyPika in eine andere gute Option für SQL-Anweisungen zu bauen. Anwendungsbeispiel (basierend auf einem Beispiel auf die Homepage des Projektes):

>>> from pypika import Order, Query
>>> Query.from_('customers').select('id', 'fname', 'lname', 'phone').orderby('id', order=Order.desc)
SELECT "id","fname","lname","phone" FROM "customers" ORDER BY "id" DESC

Wenn Sie django Sie möglicherweise die zitierte Funktion verwenden möchten, die automatisch an die aktuell konfigurierten DBMS angepasst ist:

from django.db import backend
my_quoted_variable = backend.DatabaseOperations().quote_name(myvar)
import re

def db_quote(s):
  return "\"" + re.escape(s) + "\""

kann die Arbeit einfacher machen zu zitieren, der zumindest mit MySQL arbeitet. Was wir wirklich brauchen, ist jedoch cursor.format () Funktion, die wie cursor.execute funktionieren würde (), außer es die resultierende Abfrage anstelle der Ausführung zurückgeben würde. Es gibt Zeiten, wenn Sie nicht wollen, die Abfrage ganz noch ausgeführt werden - z. B. Sie können es loggen seine ersten, oder es für das Debuggen auszudrucken, bevor Sie voran gehen mit ihm

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top