【问题标题】:Wish to observe stored procedures that exist on multiple database and across multiple servers希望观察存在于多个数据库和多个服务器上的存储过程
【发布时间】:2013-01-27 05:06:34
【问题描述】:

在 MS SQL 2005 Enterprise 多台服务器上遇到问题,我想在其中获取跨多台服务器和多个数据库的元数据集合。我在 Stack Overflow 上看到了一个使用神奇 sp_MSforeachdb 的好例子,我在下面稍作修改。基本上,一个 MS 存储过程是动态运行的,它随时都在寻找数据库(?)就像一个名字,比如“Case(fourspaces)”。这很棒,它给了我我想要的东西,但只有一个服务器。我想这样做更多,是否有可能是 SQL 大师?

到目前为止的示例:

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

有没有办法在 SQL、Linq 或 ADO.NET 中执行此操作来执行这个巧妙的内置存储过程,该存储过程插入到表变量中以跨服务器多次执行此操作但是......放那个在一组中。据我所知,您不能在 SQL Management Studio 的单个会话中切换服务器,但我很想在那个会话中被证明是错误的。

EG:我有一个有 8 台服务器的生产环境,每台服务器都有很多数据库。我可以多次运行它,但我希望如果服务器已经链接,我可以以某种方式从 sys 视图中执行此操作。但是,我在使用 SQL 2005 的环境中并获得了 MS 的 sys 视图下载,看起来 sys.servers 位于一个独立的岛屿上,其中 SERVERID 似乎没有加入任何其他内容。

我愿意在 C# 环境中使用 ADO.NET 阅读器或 LINQ,并且可能多次调用上述 TSQL 代码,但是......有没有更有效的方法可以直接在 TSQL IF 中获取信息服务器是链接服务器?只是好奇。

此操作的总体目的是用于部署目的,以查看所有服务器和数据库中存在多少过程。现在我们确实有来自 Redgate 的 SQL 比较,但我不知道它是否可以将不存在的 proc 脚本编写为与集合 A 相同的存在。即使可以,如果可行的话,我想尝试自己做一些事情。

非常感谢任何帮助,如果您需要进一步说明,请询问。

【问题讨论】:

  • 如果我要改写您的问题:给定一个服务器列表,您希望能够对所有(?)数据库运行查询,以查看他们有多少存储过程符合某种命名模式(Case____)?
  • 关闭。我想针对所有过程或用户提示搜索对与 (Case____) 数据库上的模式匹配的所有数据库运行查询。最终用户会做一个像这样的输入
  • 执行 spgetdeploystats @PROCEDURENAME
  • 其中@PROCEDURENAME 是要在所有服务器上搜索的过程的名称。 (对不起,骗人的帖子,没有意识到输入会停止评论)

标签: c# linq sql-server-2005 tsql ado.net


【解决方案1】:

我想通了,一旦您设置了链接服务器,您只需将链接服务器名称扩展到对象的左侧,以更清楚地限定它。

EG 而不是 sp_msforeachdb 我可以做 (Servername).MASTER..sp_msforeachdb。然后,如果它们是 sys.servers 表中的 LINKED(在我的情况下),我可以遍历我的服务器。

我做了一些事情,我的左连接会减慢速度,我会立即存储所有内容,然后使用“like”语句而不是显式限定符进行检查。但总的来说,我认为这个解决方案将为最终用户提供不知道要寻找的对象的确切名称的灵活性。我也喜欢我现在可以将它与 SSIS、SSRS 和 ADO.NET 一起使用,因为该过程可以为我执行搜索迭代,我不必在应用程序内存中执行某些操作,而是在 SQL 服务器上执行操作。我相信其他人可能有更好的想法,但我没有听到任何消息,所以这是我的:

完整解决方案如下:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 2020-02-08
    • 1970-01-01
    • 2021-07-04
    • 2019-10-28
    • 2017-03-13
    相关资源
    最近更新 更多