programing

Python SQL 쿼리 문자열 형식 지정

telecom 2023. 7. 24. 22:17
반응형

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테이블에서 필드1, 필드2, 필드3, 필드4\n_____를 선택합니다. 여기서 조건1=1 \n___ 및 조건2=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 문자열을 인쇄할 때 추가적인 공백을 좋아하지 않습니다.

당신은 다른 선택지를 알고 계십니까?

그렇게 오래된 스레드에 게시해서 죄송합니다. 하지만 저는 '최고'라는 비단뱀에 대한 열정을 공유하는 사람으로서 우리의 해결책을 공유해야겠다고 생각했습니다.

솔루션은 옵션 2와 옵션 4 사이의 어딘가에서 인증될 수 있는 python의 String Literal Connection(http://docs.python.org/), 을 사용하여 SQL 문을 구축하는 것입니다.

코드 샘플:

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

f-string과 함께 작동합니다.

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을 마음에 들지 않는 방식으로 작성하는 대신 디버그 로깅에 사용하는 '인쇄' 문을 변경하는 것은 어떻습니까?위의 원하는 옵션을 사용하여 다음과 같은 로깅 기능을 사용해 보십시오.

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

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

'sqlparse' 라이브러리를 사용하여 sqls를 포맷할 수 있습니다.

>>> import sqlparse
>>> raw = 'select * from foo; select * from bar;'
>>> print(sqlparse.format(raw, reindent=True, keyword_case='upper'))
SELECT *
FROM foo;

SELECT *
FROM bar;

참조: https://pypi.org/project/sqlparse/

사용할 수 있습니다.inspect.cleandoc인쇄된 SQL 문의 형식을 변경할 수 있습니다.

이 옵션은 옵션 2와 매우 잘 작동합니다.

고: 더print("-"*40)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()

출력:

----------------------------------------

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

문서에서:

inspect.cleandoc(doc)

코드 블록으로 정렬하도록 들여쓰기된 문서 문자열의 들여쓰기를 정리합니다.

첫 번째 줄에서 선행 공백이 모두 제거됩니다.두 번째 줄부터 균일하게 제거할 수 있는 선행 공백은 모두 제거됩니다.시작과 끝의 빈 줄은 이후에 제거됩니다.또한 모든 탭이 공백으로 확장됩니다.

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

이것은 @aand의 약간 수정된 버전입니다.원시 문자열의 경우 문자열 앞에 'r' 문자를 붙입니다.예:

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

이는 쿼리에 '\'와 같은 특수 문자가 있어 이스케이프가 필요하고 flake8과 같은 보풀 도구가 오류로 보고되는 경우에 권장됩니다.

Google 스타일 가이드: https://google.github.io/styleguide/pyguide#310-strings

다중 줄 문자열은 프로그램의 나머지 부분 들여쓰기와 함께 흐르지 않습니다.줄 줄 합니다.textwrap.dedent()줄의 하려면: " " " " " " " " " " "

  Yes:
  import textwrap

  long_string = textwrap.dedent("""\
      This is also fine, because textwrap.dedent()
      will collapse common leading spaces in each line.""")

은 한 일치하는 삼중 수 ."""또는'''트리플 따옴표를 사용할 때 줄의 끝은 이스케이프할 필요가 없지만 문자열에 포함됩니다.다음을 추가하여 줄의 끝 문자를 방지할 수 있습니다.\줄의 맨 끝에

다음은 하나의 이스케이프를 사용하여 원하지 않는 초기 빈 줄을 방지합니다.

example = """\
    SELECT FROM"""

그래서 옵션 2가 수정되었습니다.

import textwrap

def query():
    sql = textwrap.dedent("""\
        SELECT field1, field2, field3, field4
        FROM table
        WHERE condition1=1
        AND condition2=2""")
    con = mymodule.get_connection()
    ...

repr(sql):

'SELECT field1, field2, field3, field4\nFROM table\nWHERE condition1=1\nAND condition2=2'

완전히 포맷되지 않으려면 절차를 사용하는 것이 가장 좋은 해결책이라고 생각합니다.

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

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)을 사용하여 멋진 방식으로 인쇄하려면 항상 별도의 모듈을 사용할 수 있습니다.

한 줄 또는 두 줄에 맞는 짧은 쿼리의 경우 위의 상위 투표 솔루션에서 문자열 리터럴 솔루션을 사용합니다.더 긴 질문은 다음과 같이 분류합니다..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 스크립트가 자체 구문 강조 표시와 함께 자체 파일에 완전히 포함됩니다.

기본 사용자를 위한 문자열 형식에 대한 빠른 도움말 공유!데이터 과학 프로젝트에서 사용해야 하는 Python 문자열 형식 지정 방법은 무엇입니까?

sql = """\
select field1, field2, field3, field4
from table
where condition1=1
and condition2=2
"""

[댓글에 대한 응답으로 편집]
메소드 안에 SQL 문자열이 있다고 해서 메소드를 "표화"해야 하는 것은 아닙니다.

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

언급URL : https://stackoverflow.com/questions/5243596/python-sql-query-string-formatting

반응형