डेटाबेस संदर्भ में कॉल करने के लिए केंद्रीय संग्रहीत कार्यविधि


17

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

उदाहरण के लिए (नीचे का कोड):

  • डेटाबेस 6 के खिलाफ क्वेरी चलता है [अनुरोध] डेटाबेस के लिए जानकारी 1-10 से पता चलता है।
  • डेटाबेस 3 के विरुद्ध क्वेरी रन केवल डेटाबेस 3 के लिए [अनुरोधित] जानकारी दिखाता है।

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

कोड:

ALTER PROCEDURE [dbo].[GetFragStats] 
    @databaseName   NVARCHAR(64) = NULL
    ,@tableName     NVARCHAR(64) = NULL
    ,@indexID       INT          = NULL
    ,@partNumber    INT          = NULL
    ,@Mode          NVARCHAR(64) = 'DETAILED'
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @databaseID INT, @tableID INT

    IF @databaseName IS NOT NULL
        AND @databaseName NOT IN ('tempdb','ReportServerTempDB')
    BEGIN
        SET @databaseID = DB_ID(@databaseName)
    END

    IF @tableName IS NOT NULL
    BEGIN
        SET @tableID = OBJECT_ID(@tableName)
    END

    SELECT D.name AS DatabaseName,
      T.name AS TableName,
      I.name AS IndexName,
      S.index_id AS IndexID,
      S.avg_fragmentation_in_percent AS PercentFragment,
      S.fragment_count AS TotalFrags,
      S.avg_fragment_size_in_pages AS PagesPerFrag,
      S.page_count AS NumPages,
      S.index_type_desc AS IndexType
    FROM sys.dm_db_index_physical_stats(@databaseID, @tableID, 
           @indexID, @partNumber, @Mode) AS S
    JOIN 
       sys.databases AS D ON S.database_id = D.database_id
    JOIN 
       sys.tables AS T ON S.object_id = T.object_id
    JOIN 
       sys.indexes AS I ON S.object_id = I.object_id
                        AND S.index_id = I.index_id
    WHERE 
        S.avg_fragmentation_in_percent > 10
    ORDER BY 
        DatabaseName, TableName, IndexName, PercentFragment DESC    
END
GO

4
@JoachimIsaksson को लगता है कि सवाल यह है कि उनके रखरखाव डेटाबेस में प्रक्रिया की एक एकल प्रति कैसे हो, जो प्रत्येक डेटाबेस में प्रक्रिया की एक प्रति लगाने के बजाय अन्य डेटाबेस में DMV का संदर्भ देती है।
हारून बर्ट्रेंड

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

(नोट अपने वर्तमान दृष्टिकोण तथ्य ही नाम के दो टेबल दो अलग स्कीमा के तहत हो सकता है कि ध्यान नहीं देता है कि -। मेरा उत्तर में दिए गए सुझावों आप इनपुट और / या उत्पादन के हिस्से के रूप स्कीमा नाम पर विचार कर सकते के अलावा)
आरोन बर्ट्रेंड

जवाबों:


15

एक तरीका यह होगा कि आप एक सिस्टम प्रक्रिया करें masterऔर फिर अपने रखरखाव डेटाबेस में एक आवरण बनाएँ। ध्यान दें कि यह केवल एक समय में एक डेटाबेस के लिए काम करेगा।

सबसे पहले, गुरु में:

USE [master];
GO
CREATE PROCEDURE dbo.sp_GetFragStats -- sp_prefix required
  @tableName    NVARCHAR(128) = NULL,
  @indexID      INT           = NULL,
  @partNumber   INT           = NULL,
  @Mode         NVARCHAR(20)  = N'DETAILED'
AS
BEGIN
  SET NOCOUNT ON;

  SELECT
    DatabaseName    = DB_NAME(),
    TableName       = t.name,
    IndexName       = i.name,
    IndexID         = s.index_id,
    PercentFragment = s.avg_fragmentation_in_percent,
    TotalFrags      = s.fragment_count,
    PagesPerFrag    = s.avg_fragment_size_in_pages,
    NumPages        = s.page_count,
    IndexType       = s.index_type_desc
    -- shouldn't s.partition_number be part of the output as well?
  FROM sys.tables AS t
  INNER JOIN sys.indexes AS i
    ON t.[object_id] = i.[object_id]
    AND i.index_id = COALESCE(@indexID, i.index_id)
    AND t.name = COALESCE(@tableName, t.name)
  CROSS APPLY
    sys.dm_db_index_physical_stats(DB_ID(), t.[object_id], 
      i.index_id, @partNumber, @Mode) AS s
  WHERE s.avg_fragmentation_in_percent > 10
  -- probably also want to filter on minimum page count too
  -- do you really care about a table that has 100 pages?
  ORDER BY 
    DatabaseName, TableName, IndexName, PercentFragment DESC;
END
GO
-- needs to be marked as a system object:
EXEC sp_MS_MarkSystemObject N'dbo.sp_GetFragStats';
GO

अब, अपने रखरखाव डेटाबेस में, संदर्भ को सही ढंग से सेट करने के लिए डायनेमिक SQL का उपयोग करने वाला रैपर बनाएँ:

USE YourMaintenanceDatabase;
GO
CREATE PROCEDURE dbo.GetFragStats
  @DatabaseName SYSNAME,      -- can't really be NULL, right?
  @tableName    NVARCHAR(128) = NULL,
  @indexID      INT           = NULL,
  @partNumber   INT           = NULL,
  @Mode         NVARCHAR(20)  = N'DETAILED'
AS
BEGIN
  DECLARE @sql NVARCHAR(MAX);

  SET @sql = N'USE ' + QUOTENAME(@DatabaseName) + ';
    EXEC dbo.sp_GetFragStats @tableName, @indexID, @partNumber, @Mode;';

  EXEC sp_executesql 
    @sql,
    N'@tableName NVARCHAR(128),@indexID INT,@partNumber INT,@Mode NVARCHAR(20)',
    @tableName, @indexID, @partNumber, @Mode;
END
GO

(कारण डेटाबेस का नाम वास्तव में नहीं हो सकता NULLहै क्योंकि आप चीजों में शामिल नहीं हो सकते हैं sys.objectsऔर sys.indexesचूंकि वे प्रत्येक डेटाबेस में स्वतंत्र रूप से मौजूद हैं। इसलिए उदाहरण-विस्तृत जानकारी चाहते हैं तो शायद एक अलग प्रक्रिया हो।)

अब आप इसे किसी भी अन्य डेटाबेस के लिए कॉल कर सकते हैं, जैसे

EXEC YourMaintenanceDatabase.dbo.GetFragStats 
  @DatabaseName = N'AdventureWorks2012',
  @TableName    = N'SalesOrderHeader';

और आप हमेशा synonymप्रत्येक डेटाबेस में एक बना सकते हैं ताकि आपको रखरखाव डेटाबेस के नाम का संदर्भ भी न देना पड़े:

USE SomeOtherDatabase;`enter code here`
GO
CREATE SYNONYM dbo.GetFragStats FOR YourMaintenanceDatabase.dbo.GetFragStats;

एक अन्य तरीका डायनेमिक SQL का उपयोग करना होगा, हालांकि, यह भी, एक समय में केवल एक डेटाबेस के लिए काम करेगा:

USE YourMaintenanceDatabase;
GO
CREATE PROCEDURE dbo.GetFragStats
  @DatabaseName SYSNAME,
  @tableName    NVARCHAR(128) = NULL,
  @indexID      INT           = NULL,
  @partNumber   INT           = NULL,
  @Mode         NVARCHAR(20)  = N'DETAILED'
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @sql NVARCHAR(MAX) = N'SELECT
    DatabaseName    = @DatabaseName,
    TableName       = t.name,
    IndexName       = i.name,
    IndexID         = s.index_id,
    PercentFragment = s.avg_fragmentation_in_percent,
    TotalFrags      = s.fragment_count,
    PagesPerFrag    = s.avg_fragment_size_in_pages,
    NumPages        = s.page_count,
    IndexType       = s.index_type_desc
  FROM ' + QUOTENAME(@DatabaseName) + '.sys.tables AS t
  INNER JOIN ' + QUOTENAME(@DatabaseName) + '.sys.indexes AS i
    ON t.[object_id] = i.[object_id]
    AND i.index_id = COALESCE(@indexID, i.index_id)
    AND t.name = COALESCE(@tableName, t.name)
  CROSS APPLY
    ' + QUOTENAME(@DatabaseName) + '.sys.dm_db_index_physical_stats(
        DB_ID(@DatabaseName), t.[object_id], i.index_id, @partNumber, @Mode) AS s
  WHERE s.avg_fragmentation_in_percent > 10
  ORDER BY 
    DatabaseName, TableName, IndexName, PercentFragment DESC;';

  EXEC sp_executesql @sql, 
    N'@DatabaseName SYSNAME, @tableName NVARCHAR(128), @indexID INT,
      @partNumber INT, @Mode NVARCHAR(20)',
    @DatabaseName, @tableName, @indexID, @partNumber, @Mode;
END
GO

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

सबसे पहले, देखें:

CREATE VIEW dbo.CertainTablesAndIndexes
AS
  SELECT 
    db = N'AdventureWorks2012',
    t.[object_id],
    [table] = t.name,
    i.index_id,
    [index] = i.name
  FROM AdventureWorks2012.sys.tables AS t
  INNER JOIN AdventureWorks2012.sys.indexes AS i
  ON t.[object_id] = i.[object_id]

  UNION ALL

  SELECT 
    db = N'database2',
    t.[object_id],
    [table] = t.name,
    i.index_id,
    [index] = i.name
  FROM database2.sys.tables AS t
  INNER JOIN database2.sys.indexes AS i
  ON t.[object_id] = i.[object_id]

  -- ... UNION ALL ...
  ;
GO

फिर प्रक्रिया:

CREATE PROCEDURE dbo.GetFragStats
  @DatabaseName NVARCHAR(128) = NULL,
  @tableName    NVARCHAR(128) = NULL,
  @indexID      INT           = NULL,
  @partNumber   INT           = NULL,
  @Mode         NVARCHAR(20)  = N'DETAILED'
AS
BEGIN
  SET NOCOUNT ON;

  SELECT
    DatabaseName    = DB_NAME(s.database_id),
    TableName       = v.[table],
    IndexName       = v.[index],
    IndexID         = s.index_id,
    PercentFragment = s.avg_fragmentation_in_percent,
    TotalFrags      = s.fragment_count,
    PagesPerFrag    = s.avg_fragment_size_in_pages,
    NumPages        = s.page_count,
    IndexType       = s.index_type_desc
  FROM dbo.CertainTablesAndIndexes AS v
  CROSS APPLY sys.dm_db_index_physical_stats
    (DB_ID(v.db), v.[object_id], v.index_id, @partNumber, @Mode) AS s
  WHERE s.avg_fragmentation_in_percent > 10
    AND v.index_id = COALESCE(@indexID, v.index_id)
    AND v.[table] = COALESCE(@tableName, v.[table])
    AND v.db = COALESCE(@DatabaseName, v.db)
  ORDER BY 
    DatabaseName, TableName, IndexName, PercentFragment DESC;
END
GO

15

खैर, बुरी खबर है, अच्छी खबर है, और कुछ अच्छी खबरें हैं।

बुरी ख़बरें

T-SQL ऑब्जेक्ट उस डेटाबेस में निष्पादित होते हैं जहां वे रहते हैं। दो (बहुत उपयोगी नहीं) अपवाद हैं:

  1. डेटाबेस sp_में पहले से मौजूद नामों के साथ संग्रहीत कार्यविधियाँ और जो मौजूद हैं [master](एक बढ़िया विकल्प नहीं: एक समय में एक DB, कुछ को [master]जोड़ना, संभवतः प्रत्येक DB के लिए समानार्थक शब्द जोड़ना, जो प्रत्येक नए DB के लिए किया जाना है)
  2. अस्थायी संग्रहीत कार्यविधियाँ - स्थानीय और वैश्विक (एक व्यावहारिक विकल्प नहीं है क्योंकि उन्हें हर बार बनाना पड़ता है और आपको उन्हीं मुद्दों के साथ छोड़ना पड़ता है जो आपके पास sp_संग्रहीत खरीद के साथ हैं [master]

अच्छी खबर (एक पकड़ने के साथ)

बहुत से (शायद सबसे अधिक?) लोग वास्तव में आम मेटा-डेटा प्राप्त करने के लिए निर्मित कार्यों के बारे में जानते हैं:

इन कार्यों का उपयोग करने के लिए JOINs की आवश्यकता को समाप्त कर सकते हैं sys.databases(हालांकि यह एक वास्तव में एक समस्या नहीं है), sys.objects(पसंदीदा पर sys.tablesजो अनुक्रमित दृश्यों को छोड़कर ), और sys.schemas(आप उस एक को याद नहीं कर रहे थे, और सब कुछ dboस्कीमा ;-) में नहीं है) लेकिन चार जॉइन में से तीन को हटाने के बावजूद, हम अभी भी कार्यात्मक रूप से एक ही स्थान पर हैं, है ना? गलत-ओ!

OBJECT_NAME()और OBJECT_SCHEMA_NAME()कार्यों की अच्छी विशेषताओं में से एक यह है कि उनके पास एक वैकल्पिक दूसरा पैरामीटर है @database_id। मतलब, उन तालिकाओं में शामिल होने (को छोड़कर sys.databases) डेटाबेस-विशिष्ट है, इन कार्यों का उपयोग करने से आपको सर्वर-वाइड जानकारी मिलती है। यहां तक ​​कि OBJECT_ID () सर्वर-वाइड जानकारी के लिए इसे पूरी तरह से योग्य ऑब्जेक्ट नाम देकर अनुमति देता है।

इन मेटा-डेटा फ़ंक्शन को मुख्य क्वेरी में शामिल करके, हम वर्तमान डेटाबेस से परे एक ही समय में विस्तार करते हुए सरल कर सकते हैं। क्वेरी रिफलेक्ट करने का पहला पास हमें देता है:

SELECT  DB_NAME(stat.database_id) AS [DatabaseName],
        OBJECT_SCHEMA_NAME(stat.[object_id], stat.database_id) AS [SchemaName],
        OBJECT_NAME(stat.[object_id], stat.database_id) AS [TableName],
        ind.name AS [IndexName],
        stat.index_id AS [IndexID],
        stat.avg_fragmentation_in_percent AS [PercentFragment],
        stat.fragment_count AS [TotalFrags],
        stat.avg_fragment_size_in_pages AS [PagesPerFrag],
        stat.page_count AS [NumPages],
        stat.index_type_desc AS [IndexType]
FROM sys.dm_db_index_physical_stats(@DatabaseID, @TableID, 
        @IndexID, @PartitionNumber, @Mode) stat
INNER JOIN sys.indexes ind
        ON ind.[object_id] = stat.[object_id]
       AND ind.[index_id] = stat.[index_id]
WHERE stat.avg_fragmentation_in_percent > 10
ORDER BY DatabaseName, TableName, IndexName, PercentFragment DESC;

और अब "कैच" के लिए: इंडेक्स नाम प्राप्त करने के लिए कोई मेटा-डेटा फ़ंक्शन नहीं है, अकेले सर्वर-वाइड करें। तो है कि यह? क्या हम 90% पूर्ण हैं और अभी भी sys.indexesडेटा प्राप्त करने के लिए किसी विशेष डेटाबेस में होने की आवश्यकता है ? क्या हमें डायनामिक एसक्यूएल का उपयोग करने के लिए वास्तव में संग्रहीत प्रक्रिया बनाने की आवश्यकता है, हर बार जब हमारा मुख्य प्रोक चलता है, sys.indexesसभी डेटाबेस में सभी प्रविष्टियों का एक टेम्पर टेबल ताकि हम इसमें शामिल हो सकें? नहीं!

वास्तव में अच्छी खबर है

तो इसके साथ ही एक छोटी सी विशेषता भी है कि कुछ लोगों को नफरत करना पसंद है, लेकिन जब सही तरीके से उपयोग किया जाता है, तो कुछ आश्चर्यजनक चीजें कर सकते हैं। हां: SQLCLR। क्यों? क्योंकि SQLCLR कार्यों स्पष्ट रूप से SQL कथन प्रस्तुत कर सकते हैं, लेकिन एप्लिकेशन कोड से जमा करने के स्वभाव से ही, यह है गतिशील एसक्यूएल। इसलिए टी-एसक्यूएल कार्यों के विपरीत, SQLCLR फ़ंक्शन इसे निष्पादित करने से पहले एक डेटाबेस नाम को क्वेरी में इंजेक्ट कर सकता है। मतलब, हम अपने समारोह की क्षमता को प्रतिबिंबित करने बना सकते हैं OBJECT_NAME()और OBJECT_SCHEMA_NAME()एक लेने के लिए database_idऔर है कि डेटाबेस के लिए जानकारी मिलती है।

निम्नलिखित कोड वह कार्य है। लेकिन यह आईडी के बजाय एक डेटाबेस का नाम लेता है ताकि इसे देखने के अतिरिक्त चरण को करने की आवश्यकता न हो (जो इसे थोड़ा कम जटिल और थोड़ा तेज बनाता है)।

public class MetaDataFunctions
{
    [return: SqlFacet(MaxSize = 128)]
    [Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true,
        SystemDataAccess = SystemDataAccessKind.Read)]
    public static SqlString IndexName([SqlFacet(MaxSize = 128)] SqlString DatabaseName,
        SqlInt32 ObjectID, SqlInt32 IndexID)
    {
        string _IndexName = @"<unknown>";

        using (SqlConnection _Connection =
                                    new SqlConnection("Context Connection = true;"))
        {
            using (SqlCommand _Command = _Connection.CreateCommand())
            {
                _Command.CommandText = @"
SELECT @IndexName = si.[name]
FROM   [" + DatabaseName.Value + @"].[sys].[indexes] si
WHERE  si.[object_id] = @ObjectID
AND    si.[index_id] = @IndexID;
";

                SqlParameter _ParamObjectID = new SqlParameter("@ObjectID",
                                               SqlDbType.Int);
                _ParamObjectID.Value = ObjectID.Value;
                _Command.Parameters.Add(_ParamObjectID);

               SqlParameter _ParamIndexID = new SqlParameter("@IndexID", SqlDbType.Int);
                _ParamIndexID.Value = IndexID.Value;
                _Command.Parameters.Add(_ParamIndexID);

                SqlParameter _ParamIndexName = new SqlParameter("@IndexName",
                                                  SqlDbType.NVarChar, 128);
                _ParamIndexName.Direction = ParameterDirection.Output;
                _Command.Parameters.Add(_ParamIndexName);

                _Connection.Open();
                _Command.ExecuteNonQuery();

                if (_ParamIndexName.Value != DBNull.Value)
                {
                    _IndexName = (string)_ParamIndexName.Value;
                }
            }
        }

        return _IndexName;
    }
}

यदि आप ध्यान देंगे, हम संदर्भ कनेक्शन का उपयोग कर रहे हैं, जो न केवल तेज़ है, बल्कि SAFEअसेंबली में भी काम करता है । हां, यह एक विधानसभा के रूप में चिह्नित में काम करता हैSAFE, तो यह (या इसके रूपांतर) भी Azure SQL डेटाबेस V12 पर काम करना चाहिए (अप्रैल, 2016 में एज़्योर SQL डेटाबेस से SQLCLR के लिए समर्थन को अचानक हटा दिया गया था)

तो मुख्य प्रश्न का हमारा दूसरा पास रिफ्लेक्टरिंग हमें निम्नलिखित देता है:

SELECT  DB_NAME(stat.database_id) AS [DatabaseName],
        OBJECT_SCHEMA_NAME(stat.[object_id], stat.database_id) AS [SchemaName],
        OBJECT_NAME(stat.[object_id], stat.database_id) AS [TableName],
        dbo.IndexName(DB_NAME(stat.database_id), stat.[object_id], stat.[index_id])
                     AS [IndexName],
        stat.index_id AS [IndexID],
        stat.avg_fragmentation_in_percent AS [PercentFragment],
        stat.fragment_count AS [TotalFrags],
        stat.avg_fragment_size_in_pages AS [PagesPerFrag],
        stat.page_count AS [NumPages],
        stat.index_type_desc AS [IndexType]
FROM sys.dm_db_index_physical_stats(@DatabaseID, @TableID, 
        @IndexID, @PartitionNumber, @Mode) stat
WHERE stat.avg_fragmentation_in_percent > 10
ORDER BY DatabaseName, TableName, IndexName, PercentFragment DESC;

बस! यह SQLCLR स्केलर UDF और आपका रखरखाव T-SQL संग्रहीत प्रक्रिया दोनों एक ही केंद्रीकृत [maintenance]डेटाबेस में रह सकते हैं । और, आपको एक बार में एक डेटाबेस को संसाधित करने की आवश्यकता नहीं है; अब आपके पास सभी निर्भर जानकारी के लिए मेटा-डेटा फ़ंक्शन हैं जो सर्वर-वाइड हैं।

पुनश्च .IsNullC # कोड में इनपुट मापदंडों की कोई जाँच नहीं है क्योंकि T-SQL आवरण वस्तु को WITH RETURNS NULL ON NULL INPUTविकल्प के साथ बनाया जाना चाहिए :

CREATE FUNCTION [dbo].[IndexName]
                   (@DatabaseName [nvarchar](128), @ObjectID [int], @IndexID [int])
RETURNS [nvarchar](128) WITH EXECUTE AS CALLER, RETURNS NULL ON NULL INPUT
AS EXTERNAL NAME [{AssemblyName}].[MetaDataFunctions].[IndexName];

अतिरिक्त नोट्स:

  • यहां वर्णित विधि का उपयोग अन्य क्रॉस-डेटाबेस मेटा-डेटा फ़ंक्शंस के लापता होने की समान समस्याओं को हल करने के लिए भी किया जा सकता है। निम्न Microsoft कनेक्ट सुझाव एक ऐसे मामले का एक उदाहरण है। और, यह देखते हुए कि Microsoft ने इसे "W't Fix" के रूप में बंद कर दिया है, यह स्पष्ट है कि वे OBJECT_NAME()इस आवश्यकता को पूरा करने के लिए बिल्ट-इन फ़ंक्शन प्रदान करने में रुचि नहीं रखते हैं (इसलिए उस सुझाव पर पोस्ट किए गए वर्कअराउंड :-)।

    मेटाडेटा फ़ंक्शन को hobt_id से ऑब्जेक्ट नाम प्राप्त करने के लिए जोड़ें

  • SQLCLR का उपयोग करने के बारे में अधिक जानने के लिए, कृपया Stairway को SQLCLR श्रृंखला में देख लें , जो मैं SQL Server Central पर लिख रहा हूं (मुफ्त पंजीकरण आवश्यक है; क्षमा करें, मैं उस साइट की नीतियों को नियंत्रित नहीं करता हूं)।

  • IndexName()ऊपर दिखाए गए SQLCLR समारोह Pastebin पर एक आसान करने के लिए स्थापित लिपि में, उपलब्ध पूर्व संकलित है। स्क्रिप्ट "सीएलआर एकीकरण" सुविधा को सक्षम करता है यदि यह पहले से सक्षम नहीं है, और विधानसभा को चिह्नित किया गया है SAFE। इसे .NET फ्रेमवर्क संस्करण 2.0 के खिलाफ संकलित किया गया है ताकि यह SQL सर्वर 2005 और नए (यानी सभी संस्करण जो SQLCLR का समर्थन करता है) में काम करेगा।

    SQLCLR मेटा-डेटा फ़ंक्शन के लिए क्रॉस-डेटाबेस IndexName ()

  • यदि किसी को IndexName()SQLCLR फ़ंक्शन और 320 से अधिक अन्य फ़ंक्शन और संग्रहीत कार्यविधियों में रुचि है , तो यह SQL # लाइब्रेरी (जो मैं लेखक हूं) में उपलब्ध है। कृपया ध्यान दें कि नि: शुल्क संस्करण होने पर, Sys_IndexName फ़ंक्शन केवल पूर्ण संस्करण (समान Sys_AssemblyName फ़ंक्शन के साथ) में उपलब्ध है।

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