टी-एसक्यूएल के माध्यम से डेटाबेस को संदर्भित करना


11

मैं एक संग्रहीत प्रक्रिया लिख ​​रहा हूं जो एक डेटाबेस नाम को एक तर्क के रूप में लेता है और उस डेटाबेस के अनुक्रमित और उनके विखंडन स्तर की एक तालिका लौटाता है। यह संग्रहीत कार्यविधि हमारे डीबीए डेटाबेस (डीबी जिसमें टेबल डीबीए का उपयोग निगरानी और अनुकूलन के लिए होती है) में होगी। विचाराधीन सिस्टम सभी SQL Server 2008 R2 हैं अगर इससे कोई फर्क पड़ता है।

मेरे पास मूल क्वेरी काम कर चुकी है, लेकिन मैं अनुक्रमित वास्तविक नाम प्रदान करने की कोशिश कर रहा हूं। मेरे ज्ञान का सबसे अच्छा करने के लिए, यह जानकारी प्रत्येक व्यक्ति के sys.indexes दृश्य में निहित है। मेरी विशिष्ट समस्या उस संदर्भ को देखने की कोशिश कर रही है जो किसी अन्य डेटाबेस की संग्रहीत कार्यविधि से प्रोग्रामेटिक रूप से देखें।

वर्णन करने के लिए, यह मुद्दे पर क्वेरी का हिस्सा है:

FROM sys.dm_db_index_physical_stats(@db_id,NULL,NULL,NULL,NULL) p
INNER JOIN sys.indexes b ON p.[object_id] = b.[object_id] 
    AND p.index_id = b.index_id 
    AND b.index_id != 0

@Db_id द्वारा पहचाने गए डेटाबेस से निष्पादित होने पर क्वेरी ठीक काम करती है, क्योंकि यह उचित sys.indexes दृश्य का उपयोग कर रही है। अगर मैं इसे डीबीए डेटाबेस से कॉल करने का प्रयास करता हूं, हालांकि, यह सब शून्य हो जाता है, क्योंकि sys.indexes दृश्य गलत डेटाबेस के लिए है।

अधिक सामान्य शब्दों में, मुझे ऐसा कुछ करने में सक्षम होने की आवश्यकता है:

DECLARE @db_name NVARCHAR(255) = 'my_database';
SELECT * FROM @db_name + '.sys.indexes';

या

USE @db_name;

मैंने डेटाबेस या स्ट्रिंग डेटाबेस और OBJECT_NAME / OBJECT_ID / DB_ID कार्यों के संयोजन का उपयोग करके अन्य डेटाबेस को संदर्भित करने की कोशिश की है और कुछ भी काम नहीं कर रहा है। मैं किसी भी विचार की सराहना करता हूं जो समुदाय के पास हो सकता है, लेकिन मुझे संदेह है कि मुझे प्रत्येक व्यक्तिगत डेटाबेस में निवास करने के लिए इस संग्रहीत प्रक्रिया को फिर से करना होगा।

किसी सुझाव के लिए अग्रिम धन्यवाद।


1
आपको इस संदिग्ध I के लिए गतिशील SQL का उपयोग करने की आवश्यकता होगी ...
JNK

जवाबों:


10

इस प्रकार के प्रशासनिक कार्यों के लिए डायनेमिक SQL काम में आता है। यहाँ एक संग्रहीत प्रक्रिया से एक स्निपेट है जो मैंने लिखा था कि न केवल डीफ़्रेग्मेंटेशन स्तर मिलता है, बल्कि डीफ़्रेग्मेंटेशन करने के लिए कोड भी उत्पन्न करता है:

select @SQL = 
'
select getdate(),
       ''' + @@ServerName + ''',
       ''' + @DatabaseName + ''',
       so.Name,
       si.Name,
       db_id(''' + @DatabaseName + '''),
       ips.object_id,
       ips.index_id,
       ips.index_type_desc,
       ips.alloc_unit_type_desc,
       ips.index_depth,
       ips.avg_fragmentation_in_percent,
       ips.fragment_count,
       avg_fragment_size_in_pages,
       ips.page_count,
       ips.record_count,
       case
         when ips.index_id = 0 then ''alter table [' + @DatabaseName + '].'' + ss.name + ''.['' + so.name + ''] rebuild with (online = on)''
         else ''alter index '' + si.name + '' on [' + @DatabaseName + '].'' + ss.name + ''.['' + so.name + ''] rebuild with (online = on)''
       end
  from sys.dm_db_index_physical_stats(db_id(''' + @DatabaseName + '''),null,null,null, ''' + @SampleMode + ''') ips
  join [' + @DatabaseName + '].sys.objects so  on so.object_id = ips.object_id
  join [' + @DatabaseName + '].sys.schemas ss  on ss.schema_id = so.schema_id
  join [' + @DatabaseName + '].sys.indexes si  on si.object_id = ips.object_id
                      and si.index_id  = ips.index_id
order by so.Name, ips.index_id
'

exec (@SQL)

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

एक बात ध्यान दें ... यह SQL Server 2008R2 एंटरप्राइज़ संस्करण पर चलता है। मानक संस्करण पर "पुनर्निर्माण के साथ (ऑनलाइन = पर)" समर्थित नहीं है।
डेटागोड

1
मधुर, मेरे पास अब आपके जवाब को वोट करने के लिए पर्याप्त प्रतिनिधि है। :-) यह एक चालाक क्वेरी है, लेकिन मुझे कोड-जनरेटिंग क्वेरी को अलग करना पसंद है। मुझे पाठ को परिणाम चलाना और नौकरी में कट-एन-पेस्ट करने में सक्षम होना पसंद है। बहुत ही सुंदर समाधान सभी एक ही - धन्यवाद!
मडॉयल

8

गतिशील एसक्यूएल करने के लिए वैकल्पिक है SQLCMD है, जो आदेश पंक्ति, एक एजेंट काम कदम है, से लागू किया जा सकता है आह्वान-Sqlcmd PowerShell cmdlet या में सक्षम SSMS । SQLCMD सिंटैक्स में आपका उदाहरण होगा:

:SETVAR DatabaseName MyDatabase

SELECT * FROM $(DatabaseName).sys.indexes;

SQLCMD मोड उन विशेषताओं में से एक है जो मैं चाहता हूं कि मैं पहले के बारे में जानता हूं। बहुत सारी स्थितियों में काम।


1
यह भी बहुत सरल और सुरुचिपूर्ण PowerShell के साथ पूरा करने के लिए है। मुझे आपका दृष्टिकोण, मार्क पसंद है। +1
थॉमस स्ट्रिंगर

@ शकर अच्छा बिंदु, मैं शक्तियां cmdlet को संपादित करूंगा।
मार्क स्टोरी-स्मिथ

एक अच्छा समाधान भी, मैं इस पर भी ध्यान दूंगा।
mdoyle

यह अच्छा है, क्या टीएसक्यूएल में इसका समर्थन नहीं करने का एक अच्छा कारण है?
tbone

0

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

मुझे लगता है कि: यदि आपकी प्रक्रिया 'sp_' से शुरू होती है तो यह सार्वभौमिक रूप से दिखाई देने लगती है, और यदि आप इसे 'sys.sp_%' स्कीमा में परिभाषित करते हैं, तो इसका उपयोग अन्य DB संदर्भों में किया जा सकता है।

यह गतिशील रूप से DB_name में प्लग किए बिना कई DB में काम करने का एक वैकल्पिक तरीका प्रदान करेगा।

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