2011-05-17 2 views
0

Mon but est de générer dynamiquement en Python une requête SQL similaire àPython - Générer une mise à jour multiple ligne requête

UPDATE SURV_SCF_ID_STATUS 
    SET AGE_STATUS = CASE NAME 
     WHEN 'entityXp1' THEN '1' 
     WHEN 'entityXp3' THEN '0' 
     WHEN 'entityXpto1' THEN '1' 
     WHEN 'entityXpto3' THEN '1' 
    END 
WHERE NAME IN ('entityXp1', 'entityXp3', 'entityXpto1', 'entityXpto3') 

C'est ce que j'ai jusqu'à présent, mais se sent encore comme une bidouille horrible,

logs_age_list = [['entityXp1', '1'], ['entityXp3', '0'], ['entityXp1', '1'], ['entityXpto3', '1']] 
conditions_list = [] 
where_list = [] 
for entity, status in logs_age_list: 
conditions_list.append("\t\tWHEN %(entity)s THEN %(value)s" % locals()) 
where_list.append(entity) 

conditions_string = '\n'.join(conditions_list) 
where_string = ', '.join(where_list) 

sql = ''' 
UPDATE SURV_SCF_ID_STATUS 
    SET AGE_STATUS = CASE NAME 
%(conditions_string)s 
END 
WHERE NAME IN (%(where_string)s) 
''' % locals() 

print sql 

Existe-t-il un moyen plus évident de le faire? Je n'ai trouvé aucun module Python permettant cela.

Merci

+1

deuxième ligne du Zen de Python dit « explicite est mieux que implicite ». J'éviterais ''% locals() à tout prix. – atomocopter

+0

Ne dit-il pas aussi, "Beau est meilleur que laid/Simple est mieux que complexe"? J'ai commencé à l'utiliser à des fins de lisibilité après avoir lu wiki.python.org/moin/PythonSpeed/PerformanceTips et comme le déclare Zen, "La lisibilité compte" –

Répondre

1

Vous pouvez construire le condition_string via

conditions_string = ' '.join(["\t\tWHEN %s THEN %s\n" % (x, y) for x, y in logs_age_list]) 

et where_string comme

where_string = ', '.join([duo[0] for duo inlogs_age_list]) 

faire quelque chose comme

sql = ''' 
UPDATE SURV_SCF_ID_STATUS 
SET AGE_STATUS = CASE NAME 
%s 
END 
WHERE NAME IN (%s) 
''' % (conditions_string, where_string) 

Mais generall vous devrait essayer d'utiliser les méthodes d'exécution des modules DB pour éviter l'injection SQL.

Voici un exemple tiré de http://docs.python.org/library/sqlite3.html

# Never do this -- insecure! 
symbol = 'IBM' 
c.execute("... where symbol = '%s'" % symbol) 

# Do this instead 
t = (symbol,) 
c.execute('select * from stocks where symbol=?', t) 
+0

Mon module génère les données de sorte qu'il soit stérilisé mais comment pourrais-je avoir un mise à jour multiple avec ces précautions d'injection SLQ? Merci pour les optimisations. –