开发者

Wish to observe stored procedures that exist on multiple database and across multiple servers

Having an issue on MS SQL 2005 Enterprise multiple servers where I want to get a collection of meta data across multiple servers and multiple databases. I saw on Stack Overflow a good example on using the magical sp_MSforeachdb that I altered a little bit below. Basically a MS stored procedure is being ran dynamically and it's looking for anytime a database (?) is like a name like 'Case(fourspaces)'. This is great and it gives me what I want but for only a single server. I want to do this for more, is it possible SQL gurus?

Example thus far:

SET NOCOUNT ON
DECLARE @AllTables table (CompleteTableName varchar(256))
INSERT INTO @AllTables (CompleteTableName)
    EXEC sp_msforeachdb 'select distinct @@SERVERNAME+''.''+ ''?'' + ''.'' + p.name from [?].sys.procedures p (nolock) where ''?'' like ''Case____'''
SELECT * FROM @AllTables ORDER BY 1

Is there a wa开发者_如何转开发y though to do this in SQL, Linq, or ADO.NET to perform this clever built in stored procedure that inserts into a table variable to do this multiple times across servers BUT...... Put that in one set. As far as I know you CANNOT switch servers in a single session in SQL Management Studio but I would love to be proved wrong on that one.

EG: I have a production environment with 8 Servers, each of those servers has many databases. I could run this multiple times but I was hoping that if the servers were linked already I could do this from the sys views somehow. However I am on an environment using SQL 2005 and got MS's download for the sys views and it looks like the sys.servers is on an island unto itself where the SERVERID does not seem to join to anything else.

I would be willing to use an ADO.NET reader or LINQ in a C# environment and possibly call the above TSQL code multiple times but ...... Is there a more efficient way to get the info directly in TSQL IF the servers are LINKED SERVERS? Just curious.

The overall purpose of this operation is for deployment purposes to see how many procedures exist across all servers and databases. Now we do have SQL compare from Redgate but I am unaware if it can script procs that don't exist to exist the same as set A. Even if it could I would like to try to make something on my own if feasible.

Any help is much appreciated and if you need further clarification please ask.


I figured it out, once you set up linked servers you can merely extend the linked server name to the left of the object to qualify it more distinctly.

EG instead of sp_msforeachdb I can do (Servername).MASTER..sp_msforeachdb. I can then iterate through my servers if they are LINKED(they are in my case) from the sys.servers table.

I did some things that would slow things down with my left join and that I store everything at once and then examine with a 'like' statement instead of an explicit qualifier. But overall I think this solution will provide an end user with flexibility to not know the exact name of an object to hunt for. I also like that I can now use this with SSIS, SSRS and ADO.NET as the procedure can do the hunting iteration for me and I do not have to do something in an apps memory but on the SQL server's. I'm sure others may have better ideas but I did not hear anything so this is mine:

Complete solution below:

Create PROC [PE].[DeployChecker]
    (
        @DB     VARCHAR(128)
    ,   @Proc   VARCHAR(128) 
    )

AS 
    BEGIN 

    --declare variable for dynamic SQL
    DECLARE 
        @SQL    VARCHAR(512)
    ,   @x      int

    -- remove temp table if it exists as it should not be prepopulated.
    IF object_ID('tempdb..#Procs') IS NOT NULL
        DROP TABLE tempdb..#Procs

    -- Create temp table to catch built in sql stored procedure
    CREATE TABLE #Procs --DECLARE @Procs table 
        (
            ServerName      varchar(64)
        ,   DatabaseName    VARCHAR(128)
        ,   ObjectName      VARCHAR(256)
        )

    SET @X = 1

    -- Loops through the linked servers with matching criteria to examine how MANY there are.  Do a while loop while they exist.
    -- in our case the different servers are merely incrementing numbers so I merely do a while loop, you could be more explicit if needed.
    WHILE @X <= (SELECT count(*) FROM sys.servers WHERE name LIKE 'PCTRSQL_')
    BEGIN
        -- for some reason I can't automate the 'sp_msforeachdb' proc to take dynamic sql but I can set a variable to do it and then run it.
        SET @SQL = 'Insert Into #Procs Exec PCTRSQL' + CAST(@X AS VARCHAR(2)) + '.MASTER..sp_msforeachdb ' +
        '''select @@SERVERNAME, ''''?'''', name from [?].sys.procedures (nolock) where ''''?'''' like ''''%' + @DB + '%'''' '''

        Exec (@SQL)

        SET @X = @X + 1
    END
    ;

    -- Find distinct Server detail 
    WITH s AS 
        (
        SELECT Distinct
            ServerName
        ,   DatabaseName
        FROM #Procs 
        )
    -- do logic search in the select statement to see if there is a proc like what is searched for
    , p AS
        (
        SELECT 
            ServerName
        ,   DatabaseName
        ,   CASE WHEN ObjectName LIKE '%' + @Proc + '%' THEN ObjectName END AS ProcName
        FROM #Procs
        where  ObjectName LIKE '%' + @Proc + '%'
        )
    --  now do a left join from the distinct server cte to the lookup for the proc cte, we want to examine ALL the procs that match a critera
    --  however if nothing eixsts we wish to show a NULL value of a single row for a reference to the Servername and Database

    SELECT 
        s.ServerName
    ,   s.DatabaseName
    ,   p.ProcName
    ,   CAST(CASE WHEN ProcName IS NOT NULL THEN 1 ELSE 0 END AS bit) AS ExistsInDB
    FROM s
        LEFT JOIN p ON s.ServerName = p.ServerName 
            AND s.DatabaseName = p.DatabaseName
        ORDER BY DatabaseName, ServerName, ProcName

END
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜