[python] 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 ‘\ n 테이블에서 field1, field2, field3, field4 \ n_ _ ___ 선택 \ n _ ___ where condition1 = 1 \ n _ ___ _and condition2 = 2′

참고 : 공백 _은 편집기에 의해 잘 리기 때문에 밑줄로 대체 했습니다.

옵션 3

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 문자열을 인쇄 할 때 추가 공백이 마음에 들지 않습니다.

다른 옵션을 알고 있습니까?



답변

그런 오래된 스레드에 게시 해 주셔서 죄송합니다.하지만 비단뱀 같은 ‘최고’에 대한 열정도 공유하는 사람으로서 저는 우리의 솔루션을 공유 할 것이라고 생각했습니다.

해결책은 파이썬의 문자열 리터럴 연결 ( http://docs.python.org/)을 사용하여 SQL 문을 빌드하는 것입니다. )을 하는 것입니다. 이는 옵션 2와 옵션 4 사이의 어딘가에 자격을 부여 할 수 있습니다.

코드 샘플 :

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

f- 문자열 과도 잘 작동합니다 .

fields = "field1, field2, field3, field4"
table = "table"
conditions = "condition1=1 AND condition2=2"

sql = (f"SELECT {fields} "
       f"FROM {table} "
       f"WHERE {conditions};")

장점 :

  1. 비단뱀의 ‘잘 표로 만들어진’형식을 유지하지만 불필요한 공백 문자를 추가하지 않습니다 (로깅을 오염).
  2. 옵션 4의 백 슬래시 연속 추악함을 피하여 문을 추가하기 어렵게 만듭니다 (공백 블라인드는 말할 것도 없음).
  3. 또한 VIM에서 문을 확장하는 것은 정말 간단합니다 (커서를 삽입 지점에 놓고 SHIFT-O 를 눌러 새 줄을 엽니 다).


답변

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)

이렇게하면 줄이 원하는 길이보다 길 경우 로깅 된 문자열을 여러 줄로 분할하는 추가 논리를 추가하는 것도 간단합니다.


답변

내가 본 가장 깨끗한 방법은 SQL 스타일 가이드 에서 영감을 얻었습니다 .

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

기본적으로 절을 시작하는 키워드는 오른쪽 정렬되어야하고 필드 이름 등은 왼쪽 정렬되어야합니다. 이것은 매우 깔끔해 보이며 디버그하기도 더 쉽습니다.


답변

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'

condition의 값이 문자열이어야하는 경우 다음과 같이 할 수 있습니다.

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


답변

포맷을 완전히 피하려면 프로 시저 를 사용하는 것이 좋은 해결책이라고 생각 합니다 .

프로 시저를 호출하면 이 프로 시저에 넣을 쿼리결과를 얻을 수 있습니다 . 실제로 프로 시저 내에서 여러 쿼리를 처리 할 수 있습니다 . 호출은 마지막 으로 호출 된 쿼리 만 반환 합니다 .

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;

파이썬

sql =('call example;')


답변

필드 이름을 배열 “필드”에 넣은 다음 다음을 수행 할 수 있습니다.


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


답변

옵션 2를 고수하는 것이 좋습니다 (항상 더 복잡한 쿼리에 사용하고 있습니다 SELECT * FROM table). 좋은 방법으로 인쇄하려면 항상 별도의 모듈을 사용할 수 있습니다 .