Próbuję znaleźć najlepszy sposób formatowania ciągu zapytania sql. Kiedy debuguję moją aplikację, chciałbym rejestrować wszystkie ciągi zapytań sql i ważne jest, aby łańcuch był odpowiednio sformatowany.
opcja 1
def myquery():
sql = "select field1, field2, field3, field4 from table where condition1=1 and condition2=2"
con = mymodule.get_connection()
...
- Jest to dobre do drukowania ciągu sql.
- Nie jest to dobre rozwiązanie, jeśli łańcuch jest długi i nie mieści się w standardowej szerokości 80 znaków.
Opcja 2
def query():
sql = """
select field1, field2, field3, field4
from table
where condition1=1
and condition2=2"""
con = mymodule.get_connection()
...
Tutaj kod jest jasny, ale kiedy drukujesz ciąg zapytania sql, otrzymujesz wszystkie te irytujące białe spacje.
u '\ nwybierz pole1, pole2, pole3, pole4 \ n_ _ ___ z tabeli \ n _ ___ gdzie warunek1 = 1 \ n _ ___ _ i warunek2 = 2'
Uwaga: białe spacje zastąpiłem podkreśleniem _
, ponieważ zostały one przycięte przez edytor
Wariant 3
def query():
sql = """select field1, field2, field3, field4
from table
where condition1=1
and condition2=2"""
con = mymodule.get_connection()
...
- Nie podoba mi się ta opcja, ponieważ narusza przejrzystość dobrze sklasyfikowanego kodu.
Opcja 4
def query():
sql = "select field1, field2, field3, field4 " \
"from table " \
"where condition1=1 " \
"and condition2=2 "
con = mymodule.get_connection()
...
- Nie podoba mi się ta opcja, ponieważ całe dodatkowe wpisywanie w każdym wierszu i trudno jest również edytować zapytanie.
Dla mnie najlepszym rozwiązaniem byłaby opcja 2, ale nie lubię dodatkowych białych znaków podczas drukowania ciągu sql.
Czy znasz inne opcje?
python
sql
string-formatting
ssoler
źródło
źródło
Odpowiedzi:
Przepraszam, że piszę w tak starym wątku - ale jako ktoś, kto podziela pasję do Pythonowego „best”, pomyślałem, że podzielę się naszym rozwiązaniem.
Rozwiązaniem jest zbudowanie instrukcji SQL przy użyciu technologii String Literal Concatenation w języku Python ( http://docs.python.org/ ), która może być zakwalifikowana gdzieś pomiędzy Opcją 2 a Opcją 4
Przykład kodu:
sql = ("SELECT field1, field2, field3, field4 " "FROM table " "WHERE condition1=1 " "AND condition2=2;")
Działa również z f-stringami :
fields = "field1, field2, field3, field4" table = "table" conditions = "condition1=1 AND condition2=2" sql = (f"SELECT {fields} " f"FROM {table} " f"WHERE {conditions};")
Plusy:
źródło
"""
i użycie gotextwrap.dedent()
przed"sql query"
aby uniknąć bałaganu w ciągach SQL (które standardowo używają apostrofów)?Oczywiście rozważałeś wiele sposobów na napisanie kodu SQL w taki sposób, aby był poprawnie drukowany, ale co powiesz na zmianę instrukcji „print” używanej do logowania do debugowania, zamiast pisania kodu SQL w sposób, którego nie lubisz? Korzystając ze swojej ulubionej opcji powyżej, co powiesz na funkcję rejestrowania, taką jak ta:
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)
To również uczyniłoby trywialnym dodanie dodatkowej logiki w celu podzielenia zarejestrowanego ciągu na wiele linii, jeśli linia jest dłuższa niż żądana długość.
źródło
Najczystszy sposób, z jakim się spotkałem, jest inspirowany przewodnikiem po stylu sql .
sql = """ SELECT field1, field2, field3, field4 FROM table WHERE condition1 = 1 AND condition2 = 2; """
Zasadniczo słowa kluczowe rozpoczynające klauzulę powinny być wyrównane do prawej, a nazwy pól itp. Powinny być wyrównane do lewej. Wygląda to bardzo schludnie i jest również łatwiejsze do debugowania.
źródło
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'
jeśli wartość warunku powinna być ciągiem znaków, możesz zrobić tak:
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'"
źródło
format()
ciągów SQL, jest to główny zapach kodu.where condition1=:field1
i przekazywanie wartości jako parametrów. Jeśli używasz.format()
, będzie sposób na wstawienie a';DROP TABLE Users
do twojego SQL. Spójrz na PEP-249, aby dowiedzieć się, jak poprawnie używać parametrów. python.org/dev/peps/pep-0249/#paramstyleMożesz użyć,
inspect.cleandoc
aby ładnie sformatować wydrukowaną instrukcję SQL.Działa to bardzo dobrze z opcją 2 .
Uwaga:
print("-"*40)
służy to tylko zademonstrowaniu zbędnych pustych wierszy, jeśli nie używasz cleandoc.from inspect import cleandoc def query(): sql = """ select field1, field2, field3, field4 from table where condition1=1 and condition2=2 """ print("-"*40) print(sql) print("-"*40) print(cleandoc(sql)) print("-"*40) query()
Wynik:
---------------------------------------- select field1, field2, field3, field4 from table where condition1=1 and condition2=2 ---------------------------------------- select field1, field2, field3, field4 from table where condition1=1 and condition2=2 ----------------------------------------
Z dokumentów :
źródło
Myślę, że aby całkowicie uniknąć formatowania , dobrym rozwiązaniem jest użycie procedur .
Wywołanie procedury daje wynik dowolnego zapytania, które chcesz umieścić w tej procedurze. W rzeczywistości możesz przetwarzać wiele zapytań w ramach procedury. Wywołanie zwróci tylko ostatnie wywołane zapytanie .
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;
Pyton
sql =('call example;')
źródło
możesz umieścić nazwy pól w tablicy „pola”, a następnie:
sql = 'select %s from table where condition1=1 and condition2=2' % ( ', '.join(fields))
źródło
Sugerowałbym trzymać się opcji 2 (zawsze używam jej do zapytań bardziej złożonych niż
SELECT * FROM table
) i jeśli chcesz wydrukować ją ładnie, zawsze możesz użyć osobnego modułu .źródło
W przypadku krótkich zapytań, które mieszczą się w jednym lub dwóch wierszach, używam rozwiązania literału ciągu w powyższym rozwiązaniu z najwyższym głosowaniem. W przypadku dłuższych zapytań dzielę je na
.sql
pliki. Następnie używam funkcji opakowania, aby załadować plik i wykonać skrypt, na przykład: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)
Oczywiście to często znajduje się w klasie, więc zwykle nie muszę zdawać tego
cursor
wprost. Generalnie używamcodecs.open()
, ale to przenosi ogólną ideę. Następnie skrypty SQL są całkowicie samodzielne w swoich własnych plikach z własnym podświetlaniem składni.źródło
sql = """\ select field1, field2, field3, field4 from table where condition1=1 and condition2=2 """
[edytuj w odpowiedzi na komentarz]
Posiadanie ciągu SQL wewnątrz metody NIE oznacza, że musisz go „tabulować”:
>>> class Foo: ... def fubar(self): ... sql = """\ ... select * ... from frobozz ... where zorkmids > 10 ... ;""" ... print sql ... >>> Foo().fubar() select * from frobozz where zorkmids > 10 ; >>>
źródło
select
. W mojej odpowiedzi nie ma spacji wiodących. Co skłoniło cię do sformułowania opinii, że są takie same?