J'essaie de trouver le meilleur moyen de formater une chaîne de requête SQL. Lorsque je débogue mon application, je souhaite consigner toutes les chaînes de requête SQL dans un fichier. Il est donc important que la chaîne soit correctement formatée.
Option 1
def myquery():
sql = "select field1, field2, field3, field4 from table where condition1=1 and condition2=2"
con = mymodule.get_connection()
...
Option 2
def query():
sql = """
select field1, field2, field3, field4
from table
where condition1=1
and condition2=2"""
con = mymodule.get_connection()
...
Ici, le code est clair, mais lorsque vous imprimez la chaîne de requête SQL, vous obtenez tous ces espaces blancs gênants.
u '\ nsélectionnez champ1, champ2, champ3, champ4\n _ _ ___ de la table\n _ ___ où condition1 = 1\n _ ___ _ et condition2 = 2 '
Remarque: j'ai remplacé les espaces par le trait de soulignement _
, car ils sont supprimés par l'éditeur
Option 3
def query():
sql = """select field1, field2, field3, field4
from table
where condition1=1
and condition2=2"""
con = mymodule.get_connection()
...
Option 4
def query():
sql = "select field1, field2, field3, field4 " \
"from table " \
"where condition1=1 " \
"and condition2=2 "
con = mymodule.get_connection()
...
Pour moi, la meilleure solution serait Option 2 mais je n’aime pas les espaces blancs supplémentaires lors de l’impression de la chaîne SQL.
Connaissez-vous d'autres options?
Désolé de poster sur un si vieux fil de discussion - mais en tant que personne partageant également une passion pour «le meilleur» de Pythonic, j'ai pensé partager notre solution.
La solution consiste à créer des instructions SQL à l'aide de la concaténation de littéraux de chaînes de python ( http://docs.python.org/ ), ce qui pourrait être qualifié d'un point situé entre Option 2 et Option 4.
Exemple de code:
sql = ('select field1, field2, field3, field4 '
'from table '
'where condition1=1 '
'and condition2=2 ')
Vous avez évidemment envisagé de nombreuses façons d'écrire le code SQL de telle sorte qu'il s'imprime correctement, mais que diriez-vous de modifier l'instruction 'print' que vous utilisez pour la consignation de débogage, plutôt que d'écrire votre code SQL d'une manière qui vous déplaît? En utilisant votre option préférée ci-dessus, que diriez-vous d'une fonction de journalisation telle que celle-ci:
def debugLogSQL(sql):
print ' '.join([line.strip() for line in sql.splitlines()]).strip()
sql = """
select field1, field2, field3, field4
from table"""
if debug:
debugLogSQL(sql)
Cela rendrait également trivial l'ajout d'une logique supplémentaire pour fractionner la chaîne journalisée sur plusieurs lignes si la ligne est plus longue que la longueur souhaitée.
La façon la plus propre que j'ai rencontrée est inspirée par le guide de style sql .
sql = """
SELECT field1, field2, field3, field4
FROM table
WHERE condition1 = 1
AND condition2 = 2; """
Essentiellement, les mots-clés commençant une clause doivent être alignés à droite et les noms de champs, etc., doivent être laissés alignés. Cela semble très soigné et est plus facile à déboguer.
sql = ("select field1, field2, field3, field4 "
"from table "
"where condition1={} "
"and condition2={}").format(1, 2)
Output: 'select field1, field2, field3, field4 from table
where condition1=1 and condition2=2'
si la valeur de condition doit être une chaîne, vous pouvez faire comme ceci:
sql = ("select field1, field2, field3, field4 "
"from table "
"where condition1='{0}' "
"and condition2='{1}'").format('2016-10-12', '2017-10-12')
Output: "select field1, field2, field3, field4 from table where
condition1='2016-10-12' and condition2='2017-10-12'"
Pour éviter formater entièrement, je pense qu'une bonne solution consiste à utiliser procedures .
L'appel d'une procédure vous donne le résultat de la requête que vous souhaitez insérer dans cette procédure. Vous pouvez en fait traiter plusieurs requêtes au sein d'une procédure. L'appel renverra simplement la dernière requête qui a été appelée.
DROP PROCEDURE IF EXISTS example;
DELIMITER //
CREATE PROCEDURE example()
BEGIN
SELECT 2+222+2222+222+222+2222+2222 AS this_is_a_really_long_string_test;
END //
DELIMITER;
#calling the procedure gives you the result of whatever query you want to put in this procedure. You can actually process multiple queries within a procedure. The call just returns the last query result
call example;
sql =('call example;')
sql = """\
select field1, field2, field3, field4
from table
where condition1=1
and condition2=2
"""
._____. Avoir une chaîne SQL dans une méthode ne signifie pas que vous devez la "tabuler":
>>> class Foo:
... def fubar(self):
... sql = """\
... select *
... from frobozz
... where zorkmids > 10
... ;"""
... print sql
...
>>> Foo().fubar()
select *
from frobozz
where zorkmids > 10
;
>>>
Je suggérerais une option très facile. il suffit de mettre un r
avant la chaîneVous pouvez l'utiliser comme ci-dessous:
query=(r'SELECT f1,f2,f3 '
r'FROM table1 '
r'WHERE f4=cond1 '
r'AND f5=cond2 ')
cursor.execute(str(query))
results=cursor.fetchall()
cursor.close()
En plus de @ user590028:
Utiliser le format a été utile pour ce sur quoi je travaillais, comme ceci:
statement = (ins
"(name,standard_price,list_price,mes_type,uom_id,uom_po_id,type,procure_method,cost_method_categ_id,supply_method,sale_ok) "
"VALUE ('{0}','{1}','{2}'".format(row[1],str(row[2]),str(row[2])) + ",'fixed',1,1,'product','make_to_stock','standard',1,'buy',True) RETURNING id"
)
Et:
statement = ("INSERT INTO product_product "
"(product_tmpl_id,default_code,active,valuation) "
"VALUE "
"('{0}','{1}',True,'manual_periodic')".format(str(row[0]), row[1])
)
Je suggérerais de m'en tenir à l'option 2 (je l'utilise toujours pour les requêtes plus complexes que SELECT * FROM table
) et si vous voulez l'imprimer de manière agréable, vous pouvez toujours utiliser un module séparé .
Pour les requêtes courtes pouvant tenir sur une ou deux lignes, j'utilise la solution littérale chaîne dans la solution à vote supérieur ci-dessus. Pour les requêtes plus longues, je les décompose en fichiers .sql
. J'utilise ensuite une fonction wrapper pour charger le fichier et exécuter le script, quelque chose comme:
script_cache = {}
def execute_script(cursor,script,*args,**kwargs):
if not script in script_cache:
with open(script,'r') as s:
script_cache[script] = s
return cursor.execute(script_cache[script],*args,**kwargs)
Bien sûr, cela habite souvent dans une classe, donc je n'ai généralement pas besoin de passer explicitement cursor
. J'utilise aussi généralement codecs.open()
, mais cela donne une idée générale. Ensuite, les scripts SQL sont complètement autonomes dans leurs propres fichiers avec leur propre coloration syntaxique.
vous pouvez mettre les noms de champs dans un tableau "champs", puis:
sql = 'select %s from table where condition1=1 and condition2=2' % (
', '.join(fields))