2010-01-21 14 views
25

के साथ पोस्टग्रेज़ के लिए एसक्यूएल "LIKE" मान से बचें psycopg2 में के मूल्य से बचने के लिए एक फ़ंक्शन है पोस्टग्रेज़ के लिए ऑपरेंड?psycopg2

उदाहरण के लिए मैं तार कि स्ट्रिंग "सभी का 20%" के साथ शुरू से मिलान करने के लिए चाहते हो सकता है, इसलिए मैं कुछ इस तरह लिखना चाहते हैं:

sql = '... WHERE ... LIKE %(myvalue)s' 
cursor.fetchall(sql, { 'myvalue': escape_sql_like('20% of all') + '%' } 

वहाँ एक मौजूदा escape_sql_like समारोह है कि मैं यहां प्लग कर सकता है?

(। How to quote a string value explicitly (Python DB API/Psycopg2) की तरह सवाल, लेकिन मैं नहीं एक जवाब वहाँ मिल सकता है)

उत्तर

0

अब तक निर्मित एक समारोह को खोजने में असफल करने के बाद, एक मैंने लिखा बहुत सरल है:

def escape_sql_like(s): 
    return s.replace('\\', '\\\\').replace('%', '\\%').replace('_', '\\_') 
+0

आप "'" और' '' –

+0

@JensTimmerman भूल गए हैं, यह फ़ंक्शन केवल एक टोकन से बचता है, सामान्य क्वेरी को क्वेरी में उपयोग करने से पहले परिणाम से बचने के लिए। सही स्ट्रिंग एस्केपिंग 'standard_conforming_stings'' पर निर्भर करती है और तो पुस्तकालय कोड का उपयोग करके सबसे अच्छा किया जाता है। – Jasen

23

हाँ, यह एक असली गड़बड़ है। MySQL और PostgreSQL दोनों डिफ़ॉल्ट रूप से बैकस्लैश-एस्केप का उपयोग करते हैं। यह एक भयानक दर्द है यदि आप पैरामीटरकरण का उपयोग करने के बजाय बैकस्लैश के साथ फिर से स्ट्रिंग से बच रहे हैं, और यह एएनएसआई एसक्यूएल: 1 99 2 के अनुसार भी गलत है, जो कहता है कि सामान्य स्ट्रिंग से बचने के लिए डिफ़ॉल्ट रूप से कोई अतिरिक्त भागने वाले वर्ण नहीं हैं, और इसलिए एक शाब्दिक % या _ शामिल करने का कोई तरीका नहीं है।

मैं, अनुमान हैं सरल बैकस्लैश-बदलें विधि भी गलत हो जाता है अगर तुम बैकस्लैश-पलायन (जो खुद ANSI SQL के साथ गैर अनुपालन किया जा रहा) बंद कर देते हैं (MySQL में NO_BACKSLASH_ESCAPE sql_mode या PostgreSQL में standard_conforming_strings conf का उपयोग कर जो PostgreSQL देव अब कुछ संस्करणों के लिए करने की धमकी दे रहे हैं)।

LIKE -pattern के लिए एक स्पष्ट बचने के चरित्र को निर्दिष्ट करने के लिए एकमात्र असली समाधान छोटे ज्ञात LIKE...ESCAPE वाक्यविन्यास का उपयोग करना है। इसका उपयोग MySQL और PostgreSQL में बैकस्लैश-एस्केप के बजाय किया जाता है, जो उन्हें हर किसी के अनुरूप बनाता है और आउट-ऑफ-बैंड वर्णों को शामिल करने के लिए एक गारंटीकृत तरीका प्रदान करता है। पलायन के रूप में = संकेत के साथ उदाहरण के लिए:

# look for term anywhere within title 
term= term.replace('=', '==').replace('%', '=%').replace('_', '=_') 
sql= "SELECT * FROM things WHERE description LIKE %(like)s ESCAPE '='" 
cursor.execute(sql, dict(like= '%'+term+'%')) 

यह PostgreSQL, MySQL, और ANSI SQL अनुरूप डेटाबेस पर काम करता है (जो अलग db मॉड्यूल पर परिवर्तन निश्चित रूप से paramstyle सापेक्ष)।

एमएस एसक्यूएल सर्वर/साइबेस के साथ अभी भी कोई समस्या हो सकती है, जो स्पष्ट रूप से [a-z] -स्टाइल चरित्र समूह LIKE अभिव्यक्तियों में भी अनुमति देता है। इस मामले में आप के साथ शाब्दिक [ वर्ण से बचना चाहेंगे। हालांकि एएनएसआई एसक्यूएल के अनुसार एक ऐसे चरित्र से बचने के लिए जिसे बचने की आवश्यकता नहीं है अमान्य है! (Argh!) तो हालांकि यह अभी भी असली डीबीएमएस में काम करेगा, फिर भी आप एएनएसआई-अनुरूप नहीं होंगे। आह ...

0

आप एक Like वर्ग उपवर्गीकरण str और register an adapter for it यह वाक्य रचना की तरह सही में परिवर्तित करने के लिए (उदाहरण के लिए का उपयोग कर escape_sql_like() आप ने लिखा) बना सकते हैं।

+0

एक दिलचस्प विचार जिसे मैंने नहीं सोचा था, लेकिन आपको हमेशा 'LIKE' ऑपरेटरों (% या _) के साथ बच निकलने वाली स्ट्रिंग को गठबंधन करने की आवश्यकता होगी, अन्यथा आप भी उपयोग कर सकते हैं 'LIKE' के बजाय '='। यदि आप ऐसा करते हैं तो मुझे यकीन नहीं है कि इस दृष्टिकोण का लाभ केवल बचने के फ़ंक्शन को कॉल करने के सरल दृष्टिकोण पर है। – EMP

1

मुझे आश्चर्य है कि उपर्युक्त सभी की वास्तव में आवश्यकता है या नहीं।मैं psycopg2 उपयोग कर रहा हूँ और बस का उपयोग करने में सक्षम था:

data_dict['like'] = psycopg2.Binary('%'+ match_string +'%') 
cursor.execute("SELECT * FROM some_table WHERE description ILIKE %(like)s;", data_dict) 
+3

मेरे लिए काम नहीं किया – dfrankow

+4

यह और भी आसान हो सकता है : 'cursor.execute (" चुनें * कुछ_टेबल से वर्णन विवरण% s; ", ['foobar%']); –

0

मैं ऊपर कोड में कुछ सुधार किए निम्न कार्य करें:

def escape_sql_like(SQL): 
    return SQL.replace("'%", 'PERCENTLEFT').replace("%'", 'PERCENTRIGHT') 

def reescape_sql_like(SQL): 
    return SQL.replace('PERCENTLEFT', "'%").replace('PERCENTRIGHT', "%'") 

SQL = "SELECT blah LIKE '%OUCH%' FROM blah_tbl ... " 
SQL = escape_sql_like(SQL) 
tmpData = (LastDate,) 
SQL = cur.mogrify(SQL, tmpData) 
SQL = reescape_sql_like(SQL) 
cur.execute(SQL) 
2

तुम भी एक अलग कोण से इस समस्या को देख सकते हैं। तुम क्या चाहते हो? आप एक प्रश्न चाहते हैं कि के लिए कोई भी स्ट्रिंग तर्क तर्क के लिए '%' जोड़कर एक LIKE निष्पादित करता है। व्यक्त एक अच्छा तरीका है कि, कार्यों का सहारा के बिना और psycopg2 एक्सटेंशन हो सकता है:

sql = "... WHERE ... LIKE %(myvalue)s||'%'" 
cursor.execute(sql, { 'myvalue': '20% of all'}) 
+1

जो स्ट्रिंग से मेल खाता है 2001 की तरह सभी आतंकवाद का सबसे बुरा था – Jasen

2

इसके बजाय प्रतिशत चरित्र से बचने का, आप के बजाय PostgreSQL के regex कार्यान्वयन का उपयोग कर सकता।

उदाहरण के लिए, प्रणाली कैटलॉग के खिलाफ निम्न क्वेरी सक्रिय प्रश्नों जो autovacuuming उप-प्रणाली से नहीं कर रहे हैं की एक सूची प्रदान करेगा:

SELECT procpid, current_query FROM pg_stat_activity 
WHERE (CURRENT_TIMESTAMP - query_start) >= '%s minute'::interval 
AND current_query !~ '^autovacuum' ORDER BY (CURRENT_TIMESTAMP - query_start) DESC; 

चूंकि यह क्वेरी सिंटैक्स का उपयोग नहीं करता है 'की तरह' कीवर्ड, आप जो भी चाहते हैं वह करने में सक्षम हैं ... और पाइथन और psycopg2 के संबंध में पानी को गंदा नहीं करते हैं।

संबंधित मुद्दे