web-dev-qa-db-ja.com

Python SQLクエリ文字列のフォーマット

私はSQLクエリ文字列をフォーマットするための最良の方法を見つけようとしています。アプリケーションをデバッグするとき、すべてのsqlクエリ文字列をファイルに記録したいので、文字列が適切にフォーマットされていることが重要です。

オプション1

def myquery():
    sql = "select field1, field2, field3, field4 from table where condition1=1 and condition2=2"
    con = mymodule.get_connection()
    ...
  • これは、SQL文字列の印刷に適しています。
  • 文字列が長く、80文字の標準幅に収まらない場合は、良い解決策ではありません。

オプション2

def query():
    sql = """
        select field1, field2, field3, field4
        from table
        where condition1=1
        and condition2=2"""
    con = mymodule.get_connection()
    ...
  • ここではコードは明確ですが、SQLクエリ文字列を印刷すると、これらの迷惑な空白がすべて表示されます。

    u '\ nselect field1、field2、field3、field4\n _____fromテーブル\ n____where condition1 = 1\n____ _ and condition2 = 2 '

注:空白はアンダースコア_に置き換えました。これらはエディターによってトリミングされるためです

オプション

def query():
    sql = """select field1, field2, field3, field4
from table
where condition1=1
and condition2=2"""
    con = mymodule.get_connection()
    ...
  • このオプションは、よく表にまとめられたコードの明快さを損なうため、好きではありません。

オプション4

def query():
    sql = "select field1, field2, field3, field4 " \
          "from table " \
          "where condition1=1 " \
          "and condition2=2 "
    con = mymodule.get_connection()    
    ...
  • 各行のすべての余分な入力はクエリを編集するのも難しいため、このオプションは好きではありません。

私にとって最良の解決策はオプション2ですが、SQL文字列を印刷するときに余分な空白が好きではありません。

他のオプションを知っていますか?

77
ssoler

このような古いスレッドに投稿してすみませんが、Pythonicの「ベスト」への情熱も共有している人として、私はソリューションを共有すると思いました。

解決策は、Pythonの文字列リテラル連結( http://docs.python.org/ )を使用してSQLステートメントを構築することです。これは、オプション2とオプション4の間のどこかに修飾できます。

コードサンプル:

sql = ('select field1, field2, field3, field4 '
       'from table '
       'where condition1=1 '
       'and condition2=2 ')

長所:

  1. Pythonの「よく表形式化された」形式を保持しますが、余分なスペース文字は追加しません(ロギングを汚染します)。
  2. これにより、オプション4のバックスラッシュの継続のさが回避され、ステートメントの追加が困難になります(空白の失明は言うまでもありません)。
  3. さらに、VIM(カーソルを挿入ポイントに置き、SHIFT-O新しい行を開きます)。
114
user590028

SQLを記述して大丈夫なようにSQLを記述する多くの方法を明らかに検討しましたが、SQLを好きではない方法で記述するのではなく、デバッグロギングに使用する 'print'ステートメントを変更してはどうでしょうか。上記のお気に入りのオプションを使用して、次のようなロギング機能はどうですか:

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)

これにより、行が目的の長さより長い場合、ログに記録された文字列を複数の行に分割するためのロジックを追加することも簡単になります。

17
cdlk

私が出会った最もクリーンな方法は、 SQLスタイルガイド に触発されています。

sql = """
    SELECT field1, field2, field3, field4
      FROM table
     WHERE condition1 = 1
       AND condition2 = 2;
"""

基本的に、句を開始するキーワードは右揃えにし、フィールド名などは左揃えにする必要があります。これは非常にきれいに見え、デバッグも簡単です。

2
aandis
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'

条件の値を文字列にする必要がある場合、次のようにできます。

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'"
2
pangpang

完全にフォーマットするを回避するには、 procedures を使用するのがよい解決策だと思います。

プロシージャを呼び出すと、このプロシージャに入れる必要なクエリの結果が得られます。実際には、プロシージャ内で複数クエリの処理を実行できます。呼び出しは、最後のクエリが呼び出されただけを返します。

MYSQL

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;

Python

sql =('call example;')
0
Paroofkey
sql = """\
select field1, field2, field3, field4
from table
where condition1=1
and condition2=2
"""


>>> class Foo: ... def fubar(self): ... sql = """\ ... select * ... from frobozz ... where zorkmids > 10 ... ;""" ... print sql ... >>> Foo().fubar() select * from frobozz where zorkmids > 10 ; >>>

0
John Machin

非常に簡単なオプションをお勧めします。文字列の前にrを置くだけで、次のように使用できます。

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()
0
AB Abhi

@ user590028に加えて:

Formatの使用は、私が取り組んでいたものに役立ちました。

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"
            )

そして:

statement = ("INSERT INTO product_product "
             "(product_tmpl_id,default_code,active,valuation) "
             "VALUE "
             "('{0}','{1}',True,'manual_periodic')".format(str(row[0]), row[1])
             )
0
jmunsch

オプション2に固執することをお勧めします(私は常に、SELECT * FROM table)そして、それを素敵な方法で印刷したい場合は、常に separate module を使用できます。

0
Michal Chruszcz

1行または2行に収まる短いクエリの場合、上記の上位投票ソリューションで文字列リテラルソリューションを使用します。より長いクエリの場合は、_.sql_ファイルに分割します。次に、ラッパー関数を使用してファイルをロードし、スクリプトを実行します。

_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)
_

もちろん、これはしばしばクラス内に存在するため、通常cursorを明示的に渡す必要はありません。私は一般的にcodecs.open()も使用しますが、これは一般的な考え方を理解します。その後、SQLスクリプトは独自のファイルに完全に含まれ、独自の構文が強調表示されます。

0
Aikon

フィールド名を配列「フィールド」に入れてから、


sql = 'select %s from table where condition1=1 and condition2=2' % (
 ', '.join(fields))
0
jcomeau_ictx