كيفية أقتبس قيمة سلسلة صراحة (بايثون DB API / Psycopg2)

StackOverflow https://stackoverflow.com/questions/309945

  •  08-07-2019
  •  | 
  •  

سؤال

لبعض الأسباب، وأود أن تفعل صريحة نقلا من قيمة سلسلة (تصبح جزءا من الاستعلام 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 المستوى المنخفض المتوقع من قبل مواصفات API بيثون DB (لم أجد هذه الوظيفة في <لأ href = "http://www.python.org/dev/peps/pep-0249/" يختلط = " noreferrer "> PEP 249 وثيقة). إن لم يكن، ربما يوفر Psycopg2 هذه وظيفة؟ إن لم يكن، ربما يوفر جانغو هذه وظيفة؟ وأود أن تفضل عدم إرسال مثل هذه وظيفة نفسي ...

هل كانت مفيدة؟

المحلول

وطيب، لذلك كان من الغريب وذهبت ونظرت إلى مصدر psycopg2. تبين لي لم يكن لديك لتذهب أبعد من ذلك من المجلد الأمثلة على ذلك:)

ونعم، وهذا هو psycopg2 محددة. في الأساس، إذا كنت ترغب فقط على حد تعبير سلسلة كنت تفعل هذا:

from psycopg2.extensions import adapt

print adapt("Hello World'; DROP DATABASE World;")

ولكن ما ربما كنت ترغب في القيام به هو كتابة وتسجيل محول الخاصة بك؛

في المجلد أمثلة psycopg2 العثور على الملف "myfirstrecipe.py ' هناك مثال عن كيفية المدلى بها وأقتبس نوع معين بطريقة خاصة.

إذا كان لديك الكائنات الاشياء التي تريد القيام به، يمكنك فقط إنشاء محول الذي يتوافق مع بروتوكول "IPsycopgSQLQuote (انظر pydocs لmyfirstrecipe.py-سبيل المثال ... في الواقع هذا هو المرجعية الوحيدة التي يمكنني أن تجد لذلك الاسم) التي نقلت جوه الخاص بك ومن ثم تسجيله مثل ذلك:

from psycopg2.extensions import register_adapter

register_adapter(mytype, myadapter)

وأيضا، أمثلة أخرى مثيرة للاهتمام. إسبانيا. "dialtone.py" و <لأ href = "HTTP: // sourcecodebrowser. كوم / psycopg2 / 2.4.5 / simple_8py_source.html "يختلط =" noreferrer "> '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.

إذا كنت لا تريد أن يمر حول الاستفسارات والقيم بشكل منفصل، ثم تمرير حول قائمة المعلمات:

def make_my_query():
    # ...
    return sql, (value1, value2)

def do_it():
    query = make_my_query()
    cursor.execute(*query)

و(I ربما يكون بناء جملة خطأ cursor.execute) والنقطة هنا هي أنه لمجرد cursor.execute يأخذ عددا من الحجج، وهذا لا يعني ان لديك للتعامل مع كل منهم على حدة. يمكنك التعامل معهم قائمة واحدة.

وأنا لا أعتقد أنك تعطي أي تفكير كاف وراء تجنب الخاص بك للقيام بذلك الطريق الصحيح. من فضلك، استخدام API كما تم تصميمها ولا تحاول بجد لجعل الرمز الخاص بك أقل قابلية للقراءة عن الرجل القادم وأكثر هشاشة.

وهذا سيكون DB تعتمد. في حالة MySQLdb، على سبيل المثال، فإن الطبقة connection لديها طريقة literal التي سيتم تحويل القيمة إلى التمثيل الصحيح نجا لتمرير إلى الخلية (وهذا ما يستخدم cursor.execute).

وأتصور بوستجرس ديه شيئا من هذا القبيل، ولكن لا أعتقد أن هناك وظيفة للهروب القيم كجزء من API DB 2.0 المواصفات.

وهذه سوف تكون قاعدة البيانات التابعة (IIRC، الخلية يسمح \ كحرف هروب، في حين أن شيئا مثل أوراكل يتوقع نقلت إلى تضاعف: 'my '' quoted string').

وشخص يصحح لي إذا كنت مخطئا، ولكن الأسلوب المزدوج نقلا هو الأسلوب القياسي.

وربما يكون من المفيد النظر في ما غيرها من المكتبات التجريد ديسيبل القيام به (sqlalchemy، cx_Oracle، سكليتي، الخ).

وأنا عندي أن نسأل - ماذا تريد مضمنة القيم بدلا من ربط لهم

والتعليمات البرمجية المتكررة لديك سيحصل فقط من هذا القبيل، وفقا ل 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

إذا كنت تستخدم جانغو قد ترغب في استخدام وظيفة نقلا التي تتكيف تلقائيا إلى نظم إدارة قواعد البيانات المكونة حاليا:

from django.db import backend
my_quoted_variable = backend.DatabaseOperations().quote_name(myvar)
import re

def db_quote(s):
  return "\"" + re.escape(s) + "\""

ويمكن القيام بهذه المهمة بسيطة نقلا الذي يعمل على الأقل مع الخلية. ما نحتاج إليه حقا، على الرغم من cursor.format () وظيفة التي من شأنها أن تعمل مثل cursor.execute () إلا أنه سيعود الاستعلام الناتج بدلا من تنفيذه. هناك أوقات عندما كنت لا تريد الاستعلام ليتم تنفيذها تماما حتى الآن - منها مثلا قد ترغب في تسجيل لأول مرة، أو طباعته لتصحيح الأخطاء قبل المضي قدما في ذلك

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top