는 방법을 인용하는 문자열 값을 명시적으로(Python DB API/Psycopg2)
문제
몇 가지 이유로,내가 하고 싶은 것은 명시적을 인용하의 문자열 값(가되는 부분의 생성 SQL 쿼리)에 대한 인용을 암시적 수행 cursor.execute
방법은 내용에 의 두 번째 매개 변수입니다.
의"묵시적 인용은"나는 의미한다:
value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;"
cursor.execute( query, (value,) ) # value will be correctly quoted
내가 선호하는 무언가 다음과 같다:
value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;" % \
READY_TO_USE_QUOTING_FUNCTION(value)
cursor.execute( query ) # value will be correctly quoted, too
와 같은 낮은 수준 READY_TO_USE_QUOTING_FUNCTION
예상해서는 Python DB API 를 사양(지 등 기능 PEP249 문서).하지 않을 경우,어쩌면 Psycopg2 제공합한 기능이?하지 않을 경우,어쩌면 장고서 제공하는 기능입니까?내가 선호하는 것이 쓰지 않는 이러한 기능이다.
해결책
좋아, 그래서 나는 호기심이 많았고 가서 psycopg2의 근원을 보았다. 예제 폴더보다 더 멀리 갈 필요가 없었습니다. :)
그리고 네, 이것은 psycopg2- 특이 적입니다. 기본적으로 문자열을 인용하려면 다음을 수행합니다.
from psycopg2.extensions import adapt
print adapt("Hello World'; DROP DATABASE World;")
그러나 아마도 당신이 원하는 것은 자신의 어댑터를 작성하고 등록하는 것입니다.
psycopg2의 예제 폴더에서 파일을 찾을 수 있습니다. 'myfirstrecipe.py' 특별한 방식으로 특정 유형을 캐스팅하고 인용하는 방법의 예가 있습니다.
하고 싶은 일에 대한 객체가있는 경우 'IpsyCopgsqlquote'프로토콜을 준수하는 어댑터 만 만들 수 있습니다 (MyFirstRecipe.py-Aexample의 PYDOC 참조 ... 실제로 해당 이름에 대해 찾을 수있는 유일한 참조입니다. )) 그것은 당신의 객체를 인용 한 다음 그렇게 등록합니다.
from psycopg2.extensions import register_adapter
register_adapter(mytype, myadapter)
또한 다른 예는 흥미 롭습니다. ESP. 'DialTone.py' 그리고 'simple.py'.
다른 팁
당신이 찾고있는 것 같아요 mogrify 기능.
예시:
>>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
"INSERT INTO test (num, data) VALUES (42, E'bar')"
당신은 피하려고 하는 자신의 인용.뿐만 아니라 그것이 DB-특정으로 사람들이 지적하지만,에 결함을 인용하는 소스의 SQL injection 니다.
당신이 원하지 않는 경우하는 주위에 전달 쿼리와 값을 별도로 그 주위에 전달의 목록을 매개변수:
def make_my_query():
# ...
return sql, (value1, value2)
def do_it():
query = make_my_query()
cursor.execute(*query)
(아마의 구문은 커서입니다.실행 잘못)여기에 포인트이기 때문에 커서입니다.실행의 번호를 인수하지 않는 것을 의미가 있을 처리하는 모든이 별도로 합니다.처리할 수 있습니다 그들 중 하나로 목록입니다.
나는 당신이 이것을 올바른 방식으로 할 수있는 당신의 회피 뒤에 충분한 추론을주지 않는다고 생각합니다. API를 설계 했으므로 API를 사용하고 다음 사람을 위해 코드를 읽기 쉽지 않고 더 취약하게 만들기 위해 열심히 노력하지 마십시오.
이것은 DB 의존적 일 것입니다. 예를 들어 MySQLDB의 경우 connection
클래스는 a literal
MySQL로 전달하기 위해 값을 올바른 탈출 된 표현으로 변환하는 방법 (그게 cursor.execute
사용).
Postgres가 비슷한 것을 가지고 있다고 생각하지만 DB API 2.0 사양의 일부로 값을 탈출하는 기능이 있다고 생각하지 않습니다.
이것은 데이터베이스 종속입니다 (IIRC, MySQL은 허용합니다 \
탈출 캐릭터로서 오라클과 같은 것은 인용문이 두 배가 될 것으로 기대합니다. 'my '' quoted string'
).
내가 틀렸다면 누군가가 나를 교정하지만 이중 인용 방법은 표준 방법입니다.
다른 DB 추상화 라이브러리 (Sqlalchemy, CX_ORACLE, SQLITE 등)를 살펴볼 가치가 있습니다.
나는 물어봐야한다 - 왜 값을 바인딩하는 대신 값을 인화하고 싶습니까?
코드 스 니펫은 이렇게 얻을 수 있습니다. psycopg 확장 문서
from psycopg2.extensions import adapt
value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;" % \
adapt(value).getquoted()
cursor.execute( query ) # value will be correctly quoted, too
그만큼 getquoted
함수를 반환합니다 value
인용 및 탈출 된 문자열로서, 당신은 또한 갈 수도 있습니다. "SELECT * FROM some_table WHERE some_char_field = " + adapt(value).getquoted()
.
Pypika SQL 문을 구축하기위한 또 다른 좋은 옵션. 사용 예제 (프로젝트 홈페이지의 예제를 기반으로) :
>>> from pypika import Order, Query
>>> Query.from_('customers').select('id', 'fname', 'lname', 'phone').orderby('id', order=Order.desc)
SELECT "id","fname","lname","phone" FROM "customers" ORDER BY "id" DESC
django를 사용하는 경우 현재 구성된 DBMS에 자동으로 조정 된 인용 기능을 사용하려고 할 수 있습니다.
from django.db import backend
my_quoted_variable = backend.DatabaseOperations().quote_name(myvar)
import re
def db_quote(s):
return "\"" + re.escape(s) + "\""
적어도 MySQL에서 작동하는 간단한 인용 작업을 수행 할 수 있습니다. 그러나 우리가 실제로 필요한 것은 cursor.execute ()와 같이 작동하는 cursor.format () 함수입니다. 쿼리가 아직 실행되기를 원하지 않는 경우가 있습니다. 예를 들어 먼저 로그인하거나 앞으로 나아 가기 전에 디버깅을 위해 인쇄 할 수 있습니다.