Comment voulez-vous échapper à cordes pour SQLite/table des noms de colonne en Python?
L'approche standard pour l'utilisation de valeurs de variables dans SQLite requêtes est le "point d'interrogation style", comme ceci:
import sqlite3
with sqlite3.connect(":memory:") as connection:
connection.execute("CREATE TABLE foo(bar)")
connection.execute("INSERT INTO foo(bar) VALUES (?)", ("cow",))
print(list(connection.execute("SELECT * from foo")))
# prints [(u'cow',)]
Toutefois, cela ne fonctionne que pour la substitution des valeurs dans les requêtes. Il échoue lorsque utilisé pour la table ou la colonne des noms:
import sqlite3
with sqlite3.connect(":memory:") as connection:
connection.execute("CREATE TABLE foo(?)", ("bar",))
# raises sqlite3.OperationalError: near "?": syntax error
Ni le sqlite3
module ni PEP 249 mentionner une fonction pour échapper à des noms ou des valeurs. Sans doute c'est pour décourager les utilisateurs de l'assemblage de leurs requêtes avec des chaînes, mais il me laisse à une perte.
Quelle fonction ou technique est la plus appropriée pour l'utilisation de noms de variables pour les colonnes ou de tables SQLite? J'avais la nette préférence de ne pouvoir le faire sans toutes les autres dépendances, car je vais l'utiliser dans mon propre wrapper.
J'ai cherché mais je ne pouvais pas trouver une description claire et complète de la partie pertinente de SQLite est la syntaxe à utiliser pour écrire ma propre fonction. Je veux être sûr que cela fonctionne pour n'importe quel identificateur permise par SQLite, donc un essai-et-erreur de la solution est trop aléatoire pour moi.
SQLite utilise "
pour citer les identificateurs mais je ne suis pas sûr que juste échapper est suffisant. PHP fonction sqlite_escape_string
fonction de la documentation suggère que certaines des données binaires peuvent avoir besoin d'être échappé, mais qui peut être un caprice de la bibliothèque PHP.
Vous devez vous connecter pour publier un commentaire.
Pour convertir une chaîne en un SQLite identifiant:
"
avec""
.Mise en œuvre
Donné une chaîne unique argument, il va s'échapper et de le citer correctement ou lever une exception. Le deuxième argument peut être utilisé pour spécifier n'importe quel gestionnaire d'erreur enregistrés dans le
codecs
module. Le haut-sont:Cela ne veut pas vérifier réservés identifiants, donc si vous essayez de créer un nouveau
SQLITE_MASTER
table, il n'arrête pas de vous.Exemple D'Utilisation
Observations et Références
TEXTE
, pas binaire.SQLITE_MASTER
schéma dans la FAQstr
s, pasbytes
.sqlite3
peut gérer n'importe quelle autre chaîne unicode aussi longtemps qu'il peut être correctement codées en UTF-8. Les chaînes non valides pourrait provoquer des collisions entre Python 3.0 et Python 3.1.2 ou à peu près. Python 2 accepté ces chaînes non valides, mais c'est considéré comme un bug.A-Z -> &a-&z
et& -> &&
.La
psycopg2
documentation explicitement recommande l'utilisation normale python % ou {} mise en forme de substituer une table et les noms de colonne (ou d'autres bits de dynamique de la syntaxe), et ensuite, en utilisant le mécanisme de paramétrage de remplacer les valeurs dans la requête.Je suis en désaccord avec tout le monde qui est en train de dire "ne jamais utiliser la dynamique de la table/les noms de colonne, vous êtes en train de faire quelque chose de mal si vous avez besoin d'". - Je écrire des programmes pour automatiser des trucs avec des bases de données tous les jours, et je le fais tout le temps. Nous avons beaucoup de bases de données avec beaucoup de tables, mais ils sont tous construits sur des motifs répétés, afin générique de code pour gérer leur est extrêmement utile. La main-écrire les requêtes de tous les temps seraient beaucoup plus enclins à faire des erreurs et dangereux.
Il s'agit de ce "coffre-fort" signifie. La sagesse conventionnelle est que l'utilisation normale de python de manipulation de chaîne de placer les valeurs dans vos requêtes n'est pas "safe". C'est parce qu'il y a toutes sortes de choses qui peuvent mal se passer si vous le faites, et ces données, très souvent, provient de l'utilisateur et n'est pas sous votre contrôle. Vous avez besoin d'un 100% fiable échapper à ces valeurs correctement de sorte qu'un utilisateur ne peut pas injecter du SQL dans une valeur de données et la base de données de l'exécuter. Ainsi la bibliothèque des écrivains de faire ce travail; vous ne doit jamais l'.
Si, toutefois, vous êtes en train de rédiger générique helper code pour fonctionner sur des choses de bases de données, ces considérations ne s'appliquent pas autant. Vous êtes implicitement de donner n'importe qui peut appeler un tel code d'accès à tout le contenu de la base de données; c'est le point de l'aide du code. Alors maintenant, le problème de sécurité est de s'assurer que les données générées par l'utilisateur ne peut jamais être utilisé dans un tel code. Il s'agit d'un problème de sécurité dans le codage, et est un peu le même problème que aveuglément
exec
ing un utilisateur de la chaîne d'entrée. C'est une question distincte de l'insertion valeurs dans vos requêtes, car il vous voulez pour être en mesure de en toute sécurité poignée de l'utilisateur des données d'entrée.Donc, ma recommandation est: "faites ce que vous voulez assembler dynamiquement vos requêtes. Normal d'utilisation de python de la chaîne de création de modèles de sous la table et les noms de colonne, de la colle sur les clauses where et des jointures, toutes les bonnes (et horrible à déboguer) trucs. Mais assurez-vous que vous êtes conscient que quelles que soient les valeurs de ces codes de touche doit venir de vous, vos utilisateurs[1]. Ensuite, vous utilisez SQLite du paramètre de substitution de la fonctionnalité en toute sécurité insérer l'utilisateur les valeurs d'entrée dans vos requêtes que valeurs.
[1] Si (comme c'est le cas pour une grande partie du code que j'ai écris) vos utilisateurs sont les gens qui ont plein accès à des bases de données de toute façon, et le code est de simplifier leur travail, cette considération ne s'applique pas; vous êtes probablement l'assemblage des requêtes sur des tables spécifiées. Mais vous devriez toujours utiliser SQLite du paramètre de substitution pour vous sauver de l'inévitable véritable valeur que finalement, contient des apostrophes ou des signes de pourcentage.
psycopg2
avoir à faire avec sqlite?Si vous êtes tout à fait certain que vous avez besoin de spécifier les noms de colonnes dynamiquement, vous devez utiliser une bibliothèque qui peut le faire en toute sécurité (et se plaint à propos de choses qui sont fausses). SQLAlchemy est très bon à cela.
foo_table
maintenant représente la table avec la dynamique de schéma, mais vous ne pouvez l'utiliser que dans le contexte d'une connexion de base de données (de sorte que sqlalchemy sait le dialecte, et quoi faire avec le sql généré).Vous pouvez ensuite le problème de la
CREATE TABLE ...
. avececho=True
, sqlalchemy sera journal le sql généré, mais en général, sqlalchemy sort de sa façon de garder le sql généré hors de vos mains (de peur que vous envisagez d'utiliser à de mauvaises fins).et oui, sqlalchemy va prendre soin de tous les noms de colonnes qui nécessitent un traitement spécial, comme lorsque le nom de la colonne est un mot réservé sql
et peut vous sauver du possible, la méchanceté:
(apparemment des choses étranges se sont parfaitement légales identifiants sqlite)
La première chose à comprendre est que la table/colonne de noms ne peut pas être échappé dans le même sens que vous ne pouvez échapper à chaînes stockées en tant que valeurs de base de données.
La raison en est que soit vous avez à:
Avoir compris que, le deuxième chose à comprendre est que la façon dont vous allez vous retrouver "s'échapper" de la table/les noms de colonnes dépend de votre contexte spécifique, et donc, il n'y a plus d'une façon de faire cela, mais quelle que soit la manière, vous aurez besoin de creuser pour comprendre exactement ce qui est ou n'est pas acceptable colonne/nom de la table dans sqlite.
Pour vous aider à démarrer, voici une condition:
Mieux encore, l'utilisation de certains noms de colonne peut avoir des effets secondaires indésirables:
Tous les deux cités, les textes sont de http://www.sqlite.org/lang_createtable.html
De la sqlite faq, question 24 (la formulation de la question n'est évidemment pas donner un indice que la réponse peut être utile à votre question):
Si le nom lui-même contient des guillemets, échapper à ce double devis avec une autre.
Espaces réservés sont que pour des valeurs. La colonne et les noms de table sont structurelles, et s'apparentent à des noms de variables; vous ne pouvez pas utiliser des espaces réservés pour les remplir.
Vous disposez de trois options:
De
psycopg2
version 2.7 (sorti en Février 2017), les noms de colonnes et les noms de table (identifiants) peuvent être générées à la volée de façon sécuritaire à l'aide depsycopg2.sql
. Voici un lien vers la documentation avec des exemples: http://initd.org/psycopg/docs/sql.html.Donc, la façon d'écrire la requête dans votre question serait:
Utiliser la fonction définie spécifiquement pour cette:
Source: https://www.sqlite.org/draft/lang_corefunc.html#quote
Exemple d'utilisation:
Si vous trouvez que vous avez besoin d'une variable le nom de l'entité (soit relvar ou champ), alors vous êtes probablement faire quelque chose mal. un autre modèle serait d'utiliser une carte de propriété, quelque chose comme:
Ensuite, il suffit juste de préciser le nom de façon dynamique lors d'un insert à la place d'une colonne.