PostgreSQL में एकल उद्धरण के साथ पाठ डालें


432

मेरे पास एक टेबल है test(id,name)

मैं जैसे मूल्यों डालने की आवश्यकता: user's log, 'my user', customer's

 insert into test values (1,'user's log');
 insert into test values (2,''my users'');
 insert into test values (3,'customer's');

यदि मैं उपरोक्त कथनों में से कोई भी चलाता हूं तो मुझे एक त्रुटि मिल रही है।

यदि इसे सही ढंग से करने की कोई विधि है तो कृपया साझा करें। मैं कोई तैयार बयान नहीं चाहता।

क्या एसक्यूएल भागने तंत्र का उपयोग करना संभव है?


1
अपने ग्राहक पुस्तकालय से बचने के लिए जो भी मूल्य का उपयोग करें। अधिक जानकारी के लिए आपको कहना होगा कि आप डेटाबेस तक कैसे पहुंच रहे हैं।
रिचर्ड हूक्स्टन

@Richard Huxton डेटाबेस जावा द्वारा एक्सेस किया जाता है।
MAHI सेप

2
इसलिए मानक jdbc प्लेसहोल्डर्स का उपयोग करें। या समझाएं कि यह सबसे अच्छा विकल्प क्यों नहीं है।
रिचर्ड हूक्स्टन

@ रिचर्ड हूक्स्टन मैं यह नहीं कह रहा हूं कि यह सबसे अच्छा विकल्प नहीं है, मैं खोज रहा हूं कि क्या ऐसा करने के लिए एसक्यूएल में कोई भागने की विधि मौजूद है।
MAHI सेप

ठीक है, नीचे देखें @ क्लॉडिक्स का उत्तर, लेकिन जाहिर है कि मूल्य
शाब्दिकों

जवाबों:


763

स्ट्रिंग शाब्दिक

एकल उद्धरणों 'को बढ़ाकर उन्हें दोगुना करना -> ''निश्चित रूप से मानक तरीका और कार्य है:

'user's log'     -- incorrect syntax (unbalanced quote)
'user''s log'

पुराने संस्करणों में या यदि आप अभी भी साथ चलते हैं standard_conforming_strings = offया, आम तौर पर, यदि आप पॉसिक्स से बचने के लिए स्ट्रिंग सिंटैक्स कीE घोषणा करते हैं , तो आप बैकस्लैश के साथ भी बच सकते हैं \:

E'user\'s log'

बैकस्लैश खुद एक और बैकस्लैश के साथ बच जाता है। लेकिन यह आमतौर पर बेहतर नहीं है।
यदि आपको कई एकल उद्धरण या भागने की कई परतों से निपटना है, तो आप डॉलर-उद्धृत स्ट्रिंग्स के साथ PostgreSQL में नरक से बचने से बच सकते हैं :

'escape '' with '''''
$$escape ' with ''$$

डॉलर-उद्धरणों में भ्रम की स्थिति से बचने के लिए, प्रत्येक जोड़े में एक अद्वितीय टोकन जोड़ें:

$token$escape ' with ''$token$

जिसे किसी भी स्तर पर घोंसला बनाया जा सकता है:

$token2$Inner string: $token1$escape ' with ''$token1$ is nested$token2$

ध्यान दें यदि $चरित्र आपके क्लाइंट सॉफ़्टवेयर में विशेष अर्थ होना चाहिए। इसके अलावा आपको इससे बचना पड़ सकता है। यह Psql या pgAdmin जैसे मानक PostgreSQL ग्राहकों के मामले में नहीं है।

यह सभी plpgsql फ़ंक्शन या ad-hoc SQL कमांड लिखने के लिए बहुत उपयोगी है। यद्यपि उपयोगकर्ता इनपुट संभव है, हालांकि यह आपके आवेदन में एसक्यूएल इंजेक्शन के खिलाफ सुरक्षा के लिए तैयार बयान या किसी अन्य विधि का उपयोग करने की आवश्यकता को कम नहीं कर सकता है। @ क्रेग का जवाब उस पर अधिक है। अधिक जानकारी:

पोस्टग्रेज के अंदर मान

डेटाबेस के अंदर मूल्यों के साथ व्यवहार करते समय, स्ट्रिंग को ठीक से उद्धृत करने के लिए कुछ उपयोगी कार्य हैं:

  • quote_literal()याquote_nullable() - उत्तरार्द्ध NULLअशक्त इनपुट के लिए स्ट्रिंग आउटपुट करता है । ( मान्य SQL पहचानकर्ताओं को प्राप्त करने के लिए आवश्यक स्ट्रिंग्स quote_ident()को भी डबल-कोट करना है ।)
  • format()प्रारूप विनिर्देशक %Lके बराबर है quote_nullable()
    पसंद:format('%L', string_var)
  • concat()याconcat_ws() आमतौर पर अच्छे नहीं होते हैं क्योंकि वे नेस्टेड सिंगल कोट्स और बैकस्लैश से बच नहीं जाते हैं।

1
यह भी ध्यान देने योग्य है कि कुछ PgJDBC संस्करणों में डॉलर-उद्धरण के साथ समस्याएँ हैं - विशेष रूप से, यह डॉलर-उद्धृत स्ट्रिंग्स के भीतर स्टेटमेंट-टर्मिनेटर (?) को अनदेखा करने में विफल हो सकता है।
क्रेग रिंगर

1
इस संबंधित उत्तर में JDBC के साथ समस्या के लिए विवरण है।
इरविन ब्रान्डेसटेटर

1
और यदि आप प्रक्रियात्मक भाषा आदि के मामले में सम्मिलन पर पाठ कॉलम से बचना चाहते हैं, तो आप quot_literal (column_name) स्ट्रिंग फ़ंक्शन का उपयोग कर सकते हैं।
एलेगेल

1
$ टोकन $ भयानक है। धन्यवाद।
पौराणिक

@ErwinBrandstetter, re "किसी भी स्तर के नेस्टेड हो सकते हैं": लेकिन SELECT $outer$OUT$inner$INNER$inner$ER$outer$;यह साबित करता है कि 2nd लेवल नेस्टिंग यहां काम नहीं करती है?
फिलीप्रेम

46

यह बहुत सारी बुरी दुनिया है, क्योंकि आपका प्रश्न यह है कि आपके आवेदन में संभवतः SQL इंजेक्शन छेद है।

आपको पैरामीटराइज्ड स्टेटमेंट का उपयोग करना चाहिए। जावा के लिए, PreparedStatementप्लेसहोल्डर्स के साथ उपयोग करें । आप कहते हैं कि आप parameterised बयानों का उपयोग नहीं करना चाहते हैं, लेकिन आप की व्याख्या नहीं करते क्यों , और स्पष्ट रूप से यह एक बहुत अच्छा कारण उन्हें इस्तेमाल करने के लिए नहीं है क्योंकि वे सबसे सरल, सबसे सुरक्षित समस्या आप कोशिश कर रहे हैं ठीक करने के लिए जिस तरह से कर रहे हैं हो गया है समाधान करना।

जावा में SQL इंजेक्शन को रोकना देखें । बॉबी के अगले शिकार मत बनो ।

PgJDBC में स्ट्रिंग उद्धरण और भागने के लिए कोई सार्वजनिक कार्य नहीं है। यह आंशिक रूप से है क्योंकि यह एक अच्छा विचार की तरह लग सकता है।

वहाँ रहे हैं बिल्ट-इन कार्य के हवाले से quote_literalऔर quote_identPostgreSQL में, लेकिन वे के लिए कर रहे हैं PL/PgSQLकि उपयोग कार्यों EXECUTE। इन दिनों quote_literalमें ज्यादातर इसका पालन किया जाता है EXECUTE ... USING, जो कि मानकीकृत संस्करण है , क्योंकि यह अधिक सुरक्षित और आसान है । आप उन्हें यहाँ उस उद्देश्य के लिए उपयोग नहीं कर सकते हैं, क्योंकि वे सर्वर-साइड फ़ंक्शन हैं।


सोचिए अगर आपको ');DROP SCHEMA public;--दुर्भावनापूर्ण उपयोगकर्ता से मान मिले तो क्या होगा । आप उत्पादन करेंगे:

insert into test values (1,'');DROP SCHEMA public;--');

जो दो बयानों को तोड़ता है और एक टिप्पणी जिसे अनदेखा किया जाता है:

insert into test values (1,'');
DROP SCHEMA public;
--');

वूप्स, वहाँ अपने डेटाबेस जाता है।


मैं एक अपवाद से सहमत होना चाहता हूं - "जहां" खंड (हालांकि वह कहता है "डालें") मानों की सूची के साथ "खंड" (या "या" एस का एक गुच्छा) के हिस्से के रूप में। मुझे लगता है कि आप सूची के आकार की गणना कर सकते हैं और तैयार स्टेटमेंट को "क्लॉज" के साथ तैयार कर सकते हैं, लेकिन यह उस उपयोग के मामले में अजीब है।
रोबोप्रोग

@Ropoprog कुछ क्लाइंट ड्राइवरों के साथ आप उपयोग कर सकते हैं = ANY(?)और एक सरणी पैरामीटर।
क्रेग रिंगर

12
मैंने अक्सर DDL के साथ बूटस्ट्रैप डेटा के लिए शाब्दिक आवेषण का उपयोग किया है। आइए बस सवालों का जवाब देने की कोशिश करें जैसे कि 'आप इसे गलत कर रहे हैं'
ThatDataGuy

1
@ThatDataGuy निष्पक्ष टिप्पणी, लेकिन इस प्रश्न में ओपी ने एक टिप्पणी यह ​​कहते हुए जोड़ दी database is accessed by javaकि यह सीधे प्रश्न को संबोधित करता है। यहां आने वाले लोगों को संभावित खतरों के बारे में जागरूक करना भी बहुत महत्वपूर्ण है, विशेष रूप से दिए गए SQL इंजेक्शन सॉफ्टवेयर भेद्यता का # 1 कारण है। एक बार समस्या के बारे में पता चलने के बाद, लोग आपके बूटस्ट्रैपिंग उपयोग-मामले की तरह, जब कोई फर्क नहीं पड़ता, तब तक निर्णय ले सकते हैं।
दावोस

बिल्कुल सही। लोग कोड को बहुत कॉपी और पेस्ट भी करते हैं। मैं लोगों को इस दिन के बारे में चेतावनी देना बंद कर दूंगा जिस दिन मैं उत्पादन कोड में SQL इंजेक्शन भेद्यता देखना बंद कर देता हूं।
क्रेग रिंगर

26

के अनुसार PostgreSQL प्रलेखन (4.1.2.1 स्ट्रिंग स्थिरांक।) :

 To include a single-quote character within a string constant, write two 
 adjacent single quotes, e.g. 'Dianne''s horse'.

यह भी देखें standard_conforming_strings पैरामीटर, जो नियंत्रण बैकस्लैश काम करता है के साथ भागने या नहीं।


उत्तर के लिए धन्यवाद, लेकिन मुझे मैन्युअल रूप से प्रत्येक चार को इसका उपयोग करके बचना होगा, अगर उनका अस्तित्व ऐसा करने के लिए किसी भी कार्य में मौजूद है?
मैही

3
@MAHI अगर इस तरह का कोई फंक्शन होता है, तो यह PgJDBC में होगा, न कि पोस्टग्रेक्सेल में इसके सेल्फ में, क्योंकि एस्केपिंग क्लाइंट-साइड पर किया जाना चाहिए। ऐसा कोई दस्तावेज सार्वजनिक कार्य नहीं है क्योंकि यह एक भयानक विचार है। आपको पैरामीटर किए गए कथनों का उपयोग करना चाहिए ताकि आपको किसी भी प्रकार के संभावित अविश्वसनीय से बचने की आवश्यकता न हो।
क्रेग रिंगर

13

Postgresql में यदि आप इसमें मान सम्मिलित करना चाहते 'हैं तो इसके लिए आपको अतिरिक्त देना होगा'

 insert into test values (1,'user''s log');
 insert into test values (2,'''my users''');
 insert into test values (3,'customer''s');

ट्रिपल उद्धरण दिखाने के लिए upvote अगर आपके पास एक उद्धृत स्ट्रिंग है
winkbrace

ऊपर, जैसा कि यह एक सरल उपाय है
ktaria


2

यदि आपको Pg के अंदर काम करने की आवश्यकता है:

to_json(value)

https://www.postgresql.org/docs/9.3/static/functions-json.html#FUNCTIONS-JSON-TABLE


यह सवाल JSON से कैसे संबंधित है?
इरविन ब्रान्डेसटेटर

1
@ErwinBrandstetter, क्षमा करें, मैं बंद हो सकता हूँ .. लेकिन यह तार में उद्धरण से बच जाता है
11

1
यह एक और मामला है। आप उद्धरणों से बचने के लिए format(), quote_literal()या उपयोग कर सकते हैं quote_nullable()। देखें: stackoverflow.com/a/25143945/939860
Erwin Brandstetter

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.