दिलचस्प पोस्ट
"जारी" कीवर्ड क्या है और यह जावा में कैसे काम करता है? style.display = 'none' क्रोम में विकल्प टैग पर काम नहीं करता है, लेकिन यह फ़ायरफ़ॉक्स में है क्या मुख्य () वास्तव में सी ++ प्रोग्राम शुरू होता है? ओपनसीवी 2.3 कंपाइलिंग इशू – अपरिभाषित रिफेंस – उबंटू 11.10 फ़ायरफ़ॉक्स में jQuery एचटीएमएल () का उपयोग करता है। winnerHTML) DOM परिवर्तनों को अनदेखा करता है बाश में हैश टेबल कैसे परिभाषित करें? ActiveMQ या RabbitMQ या ZeroMQ या केवल प्रति उपयोगकर्ता एक बार पॉपअप प्रदर्शित करें विंडोज 7 टाइमिंग फ़ंक्शन – GetSystemTimeAdjustment का उपयोग कैसे करें? धूमकेतु और jQuery सी # इंटरफ़ेस विधियों को सार या आभासी क्यों घोषित नहीं किया गया है? jqgrid संपादन एक्शनआईकंस कॉलम इवेंट्स उद्देश्य सी क्लास से कॉल स्विफ्ट फ़ंक्शन फिक्स्ड आवरण के साथ बूटस्ट्रैप ग्रिड – स्टैकिंग से स्तंभ रोकें जेनमेन इटैम का नाम ऐक्शन लास्टनर को देना

मुझे एक संग्रहीत प्रक्रिया में एक टेबल नाम कैसे पार करना चाहिए?

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

मैं सोच रहा था कि यह मापदंडों के रूप में उपयोगकर्ता मूल्यों के साथ, एक संग्रहीत proc के लिए एक पैरामीटर वाली क्वेरी के रूप में क्लीनर होगा, लेकिन जब मैं अधिक निकटता से देखता हूं, तो मैं देखता हूं कि वे ऐसा क्यों कर रहे हैं … वे जिस तालिका से चयन कर रहे हैं उन उपयोगकर्ता मूल्यों पर निरंतर निर्भर

उदाहरण के लिए, एक मामले में यदि मान ("FOO", "BAR") थे, तो क्वेरी "FOO_BAR का चयन करें"

ऐसा करने का एक आसान और स्पष्ट तरीका है? सब कुछ जो मैं कोशिश कर रहा हूँ वह अपरिहार्य लगता है।

संपादित करें: मैं निश्चित रूप से, संग्रहीत proc में sql को गतिशील रूप से उत्पन्न कर सकता हूं, और exec (ब्ली), लेकिन उस समय मैं सोच रहा हूं कि क्या मैंने कुछ हासिल किया है

ईडीआईटी 2: कुछ बुद्धिमान तरीके से तालिका नामों को पुन: निष्पादित करना, एक नया स्तंभ के रूप में अलग-अलग नामों के साथ उन सभी को एक साथ रखना, यह सभी को हल करने का एक अच्छा तरीका होगा, जो कि कई लोगों ने सीधे सीधे इंगित किया है, या इनका संकेत दिया है अफसोस की बात है, यह इस मामले में एक विकल्प नहीं है।

वेब के समाधान से एकत्रित समाधान "मुझे एक संग्रहीत प्रक्रिया में एक टेबल नाम कैसे पार करना चाहिए?"

सबसे पहले, आपको इस तरह एक क्लाइंट ऐप पर एसक्यूएल कमांड रचनाएं कभी नहीं करना चाहिए, यह एसक्यूएल इंजेक्शन है। (एक व्यवस्थापक उपकरण के लिए इसका ठीक है जिसमें कोई भी खुद का निजी नहीं है, बल्कि किसी साझा उपयोग के आवेदन के लिए नहीं)।

दूसरे, हाँ, एक संग्रहित प्रक्रिया के लिए एक parametrized कॉल दोनों क्लीनर और सुरक्षित है।

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

यहाँ एक सरल अनुभवहीन उदाहरण है:

CREATE PROC spCountAnyTableRows( @PassedTableName as NVarchar(255) ) AS -- Counts the number of rows from any non-system Table, *SAFELY* BEGIN DECLARE @ActualTableName AS NVarchar(255) SELECT @ActualTableName = QUOTENAME( TABLE_NAME ) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @PassedTableName DECLARE @sql AS NVARCHAR(MAX) SELECT @sql = 'SELECT COUNT(*) FROM ' + @ActualTableName + ';' EXEC(@SQL) END 

कुछ लोगों ने काफी ही पूछा है कि यह क्यों सुरक्षित है। उम्मीद है, थोड़ा बॉबी टेबल्स यह स्पष्ट कर सकते हैं:

वैकल्पिक शब्द


अधिक प्रश्नों के उत्तर:

  1. केवल QUOTENAME सुरक्षित होने की गारंटी नहीं है एमएस हमें इसका इस्तेमाल करने के लिए प्रोत्साहित करती है, लेकिन उन्होंने यह गारंटी नहीं दी है कि यह हैकरों द्वारा बाहर नहीं किया जा सकता है। एफवाईआई, असली सुरक्षा सभी की गारंटी के बारे में है QUOTENAME के ​​साथ तालिका देखने, एक और कहानी है, यह अटूट है।

  2. इस उदाहरण के लिए QUOTENAME कड़ाई से जरूरी नहीं है, केवल INFORMATION_SCHEMA पर लुकअप अनुवाद सामान्य रूप से पर्याप्त है QUOTENAME यहां मौजूद है क्योंकि यह एक पूर्ण और सही समाधान शामिल करने के लिए सुरक्षा में अच्छा फॉर्म है यहां पर QUOTENAME वास्तव में एक अलग, लेकिन इसी तरह की संभावित समस्या के बारे में अवगत इंजेक्शन के रूप में सुरक्षित है।

(संयुक्त राष्ट्र) सौभाग्य से ऐसा करने का कोई तरीका नहीं है – आप गतिशील एसक्यूएल पीढ़ी के अलावा अन्य संग्रहीत कोड के पैरामीटर के रूप में पारित तालिका नाम का उपयोग नहीं कर सकते। जब यह तय करने की बात आती है कि एसक्यूएल कोड कहां है, तो मैं उस कोड को संचित कोड पसंद करता है। एप्लिकेशन कोड आमतौर पर तेजी से और बनाए रखने में आसान होता है।

अगर आप जिस समाधान के साथ काम कर रहे हैं, उसे पसंद नहीं है, तो मैं एक गहरी रीडिज़ाइन का सुझाव देता हूं (यानी स्कीमा / एप्लिकेशन लॉजिक बदलना ताकि आप को अब किसी भी पैरामीटर के रूप में तालिका का नाम नहीं देना होगा)।

मैं गतिशील रूप से संग्रहीत proc में एसक्यूएल उत्पन्न के खिलाफ बहस करेंगे; जो आपको परेशानी में लाना होगा और इंजेक्शन भेद्यता पैदा कर सकता है।

इसके बजाय, मैं उन सभी तालिकाओं का विश्लेषण करेगा जो क्वेरी से प्रभावित हो सकती हैं और कुछ प्रकार की गणना कर सकती हैं जो यह निर्धारित करेंगे कि क्वेरी के लिए कौन सी तालिका का उपयोग करना है।

लगता है जैसे आप एक ORM समाधान के साथ बेहतर होगा

जब मैं एक संग्रहीत कार्यविधि में डायनामिक एसक्यूएल देखता हूं,

एक बात जिस पर आप विचार कर सकते हैं, एक केस स्टेटमेंट बनाने के लिए है, जिसमें एक ही एसक्यूएल कमांड है, जिसमें प्रत्येक वैध तालिका के लिए एक बार होता है, फिर इस प्रक्रिया में एक स्ट्रिंग तालिका नाम के रूप में पास करें और मामले का चयन करें कि कौन सी कमांड चलाने के लिए है।

एक सुरक्षा व्यक्ति के रूप में जिस तरह से उपरोक्त सुझाव आपको सिस्टम टेबल से चुनने के लिए कहता है ताकि सुनिश्चित हो कि आपके पास एक मान्य तालिका है जो मेरे लिए बर्बाद ऑपरेशन की तरह दिखती है यदि कोई इंजेक्ट कर सकता है तो QUOTENAME () को पारित किया है, तो इंजेक्शन सिस्टम तालिका पर और साथ ही अंतर्निहित तालिका पर काम करेगा। यह एक उचित तालिका नाम है, यह सुनिश्चित करने के लिए इसके साथ ही यह मदद करता है, और मुझे लगता है कि उपरोक्त सुझाव एक बेहतर तरीका है क्योंकि आप QUOTENAME () सभी का उपयोग नहीं कर रहे हैं।

इन तालिकाओं में स्तंभों के सेट समान या अलग हैं या नहीं, मैं इसे लंबे समय तक दो तरीकों से रखूँगा:

1) यदि वे समान हैं, तो एक नए कॉलम का चयन न करें जिसे एक चयनकर्ता के रूप में इस्तेमाल किया जाएगा, जिसका मूल्य उपयोगकर्ता-आपूर्तिकृत पैरामीटर से प्राप्त होता है? (क्या यह एक प्रदर्शन अनुकूलन है?)

2) यदि वे अलग-अलग हैं, तो संभावना है कि उनमें से निपटना भी अलग है। जैसे, ऐसा लगता है कि अलग-अलग ब्लॉकों में चयन / संभाल कोड को अलग करना और फिर उन्हें अलग से कॉल करना मेरे लिए सबसे अधिक मॉड्यूलर दृष्टिकोण होगा। आप "से चुनें" भाग को दोहराना होगा, लेकिन इस परिदृश्य में तालिकाओं का सेट उम्मीद है कि परिमित होगा।

कॉलिंग कोड को टेबल नाम के दो मनमाने भागों को आपूर्ति करने के लिए अनुमति देने से आपको बहुत खतरनाक लगता है।

मुझे पता नहीं है कि आपके पास कई तालिकाओं में डेटा क्यों फैला है, लेकिन ऐसा लगता है कि आप बुनियादी सिद्धांतों में से एक को तोड़ रहे हैं डेटा तालिकाओं में होना चाहिए, तालिका नाम के रूप में नहीं।

अगर तालिकाओं में एक ही लेआउट अधिक या कम होता है, तो विचार करें कि डेटा को एक मेज में डालकर इसके बजाय सबसे अच्छा होगा। यह आपकी समस्या को गतिशील क्वेरी के साथ हल करेगा, और यह डेटाबेस लेआउट को और अधिक लचीला बना देगा

उपयोगकर्ता इनपुट मानों के आधार पर तालिकाओं की पूछताछ के बजाय, आप इसके बजाय प्रक्रिया चुन सकते हैं। यानी
1. एक प्रक्रिया FOO_BAR_prc बनाएँ और इसके अंदर आप क्वेरी को 'फू_बार' से चुनते हैं, इस तरह से क्वेरी को डाटाबेस से प्रीकंपल किया जाएगा।
2. फिर उपयोगकर्ता इनपुट के आधार पर अब अपने एप्लिकेशन कोड से सही प्रक्रिया निष्पादित करें।

चूंकि आपके पास लगभग 50 तालिकाओं हैं, हालांकि यह एक संभव समाधान नहीं हो सकता है, क्योंकि इसमें आपके हिस्से पर बहुत काम की आवश्यकता होगी।

वास्तव में, मैं जानना चाहता था कि कैसे संग्रहीत कार्यप्रणाली में एक तालिका बनाने के लिए तालिका का नाम कैसे पास किया जाए। कुछ उत्तर पढ़कर और मेरे अंत में कुछ संशोधन करने का प्रयास करते हुए, मैं अंत में पैरामीटर के रूप में पारित नाम के साथ एक तालिका बनाने में सक्षम था दूसरों को इसके लिए किसी भी त्रुटि की जांच करने के लिए यहां संग्रहीत प्रक्रिया है।

यूज़ [डाटाबेस नाम] जाओ / ****** ऑब्जेक्ट: स्टोर्ड प्रोक्रिडिचर [डीबीओ]। [स्पैंकरेड डायनामिकटेबल] स्क्रिप्ट दिनांक: 06/20/2015 16:56:25 ****** / SET ANSI_NULLS पर जाओ सेट QUOTED_IDENTIFIER चालू प्रक्रिया शुरू करें [dbo]। [Sp_CreateDynamicTable] @tName varchar (255) के रूप में सेशन पर निगमित; DECLARE @ SQL nvarchar (अधिकतम)

 SET @SQL = N'CREATE TABLE [DBO].['+ @tName + '] (DocID nvarchar(10) null);' EXECUTE sp_executesql @SQL 

समाप्त

@ आरबरी यंग आपको कोष्ठकों को क्वेरी स्ट्रिंग में @ ऐक्टिविटी टैबलनाम में जोड़ने की आवश्यकता नहीं है क्योंकि यह पहले से ही INFORMATION_SCHEMA.TABLES में क्वेरी से परिणाम में शामिल है। अन्यथा, निष्पादित होने पर त्रुटि (एस) हो सकती है।

PROC spCountAnyTableRows (@ PassedTableName को NVarchar (255) के रूप में बनायें) – किसी भी गैर-सिस्टम तालिका से पंक्तियों की संख्या की गणना करता है, सुरक्षित रूप से शुरू कराना DECLARE @ एक्टिविटीटैबनेट एन एन वर्कर (255)

 SELECT @ActualTableName = QUOTENAME( TABLE_NAME ) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @PassedTableName DECLARE @sql AS NVARCHAR(MAX) --SELECT @sql = 'SELECT COUNT(*) FROM [' + @ActualTableName + '];' -- changed to this SELECT @sql = 'SELECT COUNT(*) FROM ' + @ActualTableName + ';' EXEC(@SQL) 

समाप्त