AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 172619
Accepted
scarr030
scarr030
Asked: 2017-05-04 04:52:16 +0800 CST2017-05-04 04:52:16 +0800 CST 2017-05-04 04:52:16 +0800 CST

跨所有数据库部署 UDF/SP

  • 772

我是一个偶然的 DBA,没有任何脚本知识/背景。我们有一堆不同的数据库(每个客户端都有自己的数据库),它们具有相同的结构,但数据不同。也就是说,我们会定期创建每个人都需要使用的功能。这意味着我必须将这些部署到我们 120 多个数据库中的每一个。如果不“手动”将其部署到每个数据库,我该怎么做?

我以前问过这个问题,但没有什么真正有用的。我得到的答案是“使用脚本”(不可行,因为我什至不知道如何开始)、“使用 RedGate 的工具”(没有钱购买,公司也不会购买),以及“不要使用标量 UDF 开头(完全无用)。

我还被告知“只要把它放在 master 或其他数据库中,然后调用它”。这是个好主意,但很快我们的权限/登录名就会改变,我认为一个数据库用户将无法调用另一个数据库(HIPPA 等等)。

任何人都可以为我级别的“DBA”提供一些指导吗?

谢谢

更新:我发现可以将 sp_MSforeachdb 用于 DDL 语句。显然,这不是最佳实践,因为 sp_MSforeachdb 没有记录并且不受 MS“支持”。与此一样,使用风险自负。它对我来说就像一个魅力。请参阅示例 2:https ://www.mssqltips.com/sqlservertip/1414/run-same-command-on-all-sql-server-databases-without-cursors/

对于那些不想走那条路并且和我处境相似的人,请使用答案部分提供的 Johnathan Fite 的 PS 脚本。这是一个方便的脚本,尤其是当您有多个服务器/实例时。

感谢大家!

sql-server sql-server-2008-r2
  • 4 4 个回答
  • 164 Views

4 个回答

  • Voted
  1. l.lijith
    2017-05-04T05:15:46+08:002017-05-04T05:15:46+08:00

    您可以按照用户Cade Roux在对 Stack Overflow 问题Common function / stored procedures for all databases的回答中进行尝试:

    根据 SP 实际执行的操作,您希望在 master 中创建过程,将其命名sp_并标记为系统过程:

    来自Mladen Prajdić在当前数据库上下文中运行主数据库驻留存储过程:

    USE master
    go
    CREATE PROC sp_TestMasterAccess
    AS
    SELECT    * 
    FROM    information_schema.tables
    GO
    -- SS2k5 provides a stored procedure to mark the object as system
    EXEC sys.sp_MS_marksystemobject sp_TestMasterAccess
    GO
    EXEC sp_TestMasterAccess
    
    go
    USE AdventureWorks
    EXEC sp_TestMasterAccess
    
    go
    USE master 
    DROP PROC sp_TestMasterAccess
    
    • 2
  2. SqlWorldWide
    2017-05-04T06:28:15+08:002017-05-04T06:28:15+08:00

    如果您更喜欢使用 tsql 并排除系统、离线、单用户模式和可用性组 read_only 数据库,请执行以下脚本。您需要将您的代码放在我标有“将您的代码放在这里”的部分。

    USE [master];
    GO
    
    DECLARE @DatabaseName VARCHAR(32)   
    DECLARE @SQL NVARCHAR(max)
    
    
    --get engine version
    DECLARE @MajorVersion TINYINT
    SET @MajorVersion = LEFT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(4000)),CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(4000)))-1);
    
    IF OBJECT_ID('tempdb..#databases') IS NOT NULL
    BEGIN
    DROP TABLE #databases;
    END
    CREATE TABLE #databases (dbname sysname);
    
    --if pre 2012 meaning no AG
    --grab all online databases
    IF @MajorVersion < 11 -- pre-SQL2012
    BEGIN
    
           INSERT INTO #databases
           --only choose online databases and exclude single user mode
           SELECT name FROM sys.databases 
           WHERE [STATE] = 0
           AND   [user_access]=0
           AND   [NAME] NOT IN ('master','model','msdb','tempdb') ; 
    END
    ELSE --post SQL2012
    BEGIN
           INSERT INTO #databases
           ----only choose online databases and exclude single user mode
           SELECT name FROM sys.databases 
           WHERE [STATE] = 0
           AND   [user_access]=0
           AND   [NAME] NOT IN ('master','model','msdb','tempdb');  
    
    --get secondary replica db list
    IF OBJECT_ID('tempdb..#AGdatabases') IS NOT NULL
    BEGIN
    DROP TABLE #AGdatabases;
    END
    
    CREATE TABLE #AGdatabases
    (dbname SYSNAME);
    
    IF EXISTS (SELECT
    AG.name AS [Name],
    ISNULL(agstates.primary_replica, '') AS [PrimaryReplicaServerName],
    ISNULL(arstates.role, 3) AS [LocalReplicaRole]
    FROM master.sys.availability_groups AS AG
    LEFT OUTER JOIN master.sys.dm_hadr_availability_group_states as agstates
        ON AG.group_id = agstates.group_id
    INNER JOIN master.sys.availability_replicas AS AR
        ON AG.group_id = AR.group_id
    INNER JOIN master.sys.dm_hadr_availability_replica_states AS arstates
        ON AR.replica_id = arstates.replica_id AND arstates.is_local = 1
    )
    
    BEGIN
    INSERT INTO #AGdatabases
    SELECT DISTINCT
    dbcs.database_name AS [DatabaseName]
    FROM master.sys.availability_groups AS AG
    LEFT OUTER JOIN master.sys.dm_hadr_availability_group_states as agstates
       ON AG.group_id = agstates.group_id
    INNER JOIN master.sys.availability_replicas AS AR
       ON AG.group_id = AR.group_id
    INNER JOIN master.sys.dm_hadr_availability_replica_states AS arstates
       ON AR.replica_id = arstates.replica_id AND arstates.is_local = 1
    INNER JOIN master.sys.dm_hadr_database_replica_cluster_states AS dbcs
       ON arstates.replica_id = dbcs.replica_id
    LEFT OUTER JOIN master.sys.dm_hadr_database_replica_states AS dbrs
       ON dbcs.replica_id = dbrs.replica_id AND dbcs.group_database_id = dbrs.group_database_id
    WHERE ISNULL(arstates.role, 3) = 2 AND ISNULL(dbcs.is_database_joined, 0) = 1
    ORDER BY  dbcs.database_name;
    END
    --exclude secondary replica databases
    DELETE FROM #databases WHERE dbname in
    (SELECT dbname FROM #AGdatabases);
    END
    
    
    DECLARE Deploy_Code CURSOR LOCAL FOR
    SELECT dbname FROM #databases;
    
    OPEN Deploy_Code  
    FETCH NEXT FROM Deploy_Code INTO @DatabaseName  
    WHILE @@FETCH_STATUS = 0  
    BEGIN  
    
           SELECT @SQL = 'USE '+ '[' + @DatabaseName + ']' +'; '+ 'Put your code here'+ '; '
    
           --EXEC sp_executesql @SQL
           PRINT @SQL
    
    FETCH NEXT FROM Deploy_Code INTO @DatabaseName  
    END  
    CLOSE Deploy_Code  
    DEALLOCATE Deploy_Code
    
    • 2
  3. Best Answer
    Jonathan Fite
    2017-05-04T05:21:10+08:002017-05-04T05:21:10+08:00

    我以前使用过 powershell 脚本来执行此操作。我把它包括在这里。关于使用适当工具的其他答案是最好的,尽管我不同意将对象放在公共数据库中以解决您提到的问题。

    该脚本是 powershell 并使用 windows 身份验证。它实际上并没有做任何错误处理,但确实有一点可以测试数据库是否是需要更新的数据库之一。只需向它提供一个 SQL 实例列表,确定一个唯一表(或其他查询)以确定它是否是您的应用程序数据库之一,并将其​​指向包含 .sql 文件的文件夹。

    关于脚本的一些说明

    $SQLInstanceList - 这是一个文本文件的完整路径,该文件包含您希望它跳过的所有 SQL 实例。每行一个条目。

    Server1
    Server1\Instance1
    Server2
    

    $ScriptToRunDirectory - 包含要运行的 sql 文件的目录。

    $Query - 一个查询,这样当它查看数据库时,它知道应该针对它运行查询。我加入这一步是因为我假设并非每台服务器上的每个数据库都是您的应用程序数据库之一。例如,您希望跳过的 ReportServer、master、model、tempdb、其他自定义数据库等。我还假设至少有一个表对所有应用程序数据库都是通用的。因此,当它遍历每个数据库时,它会运行上述查询,实质上是检查指定的表是否存在。如果是,它将运行 $ScriptToRunDirectory 文件夹中的所有内容,否则将跳过它。

    所以脚本的基本前提如下: * 对于列出的每个 SQL 实例,连接 * 对于 SQL 实例中的每个数据库: * 运行 $Query 以确定它是否是正确的数据库类型 * 如果数据库是正确的类型然后: * 对 $SQLToRunDirectory 中的每个 .sql 文件执行。

    <#
    
        Name: Execute Script against Servers
        Author: Jonathan Fite
        Created: 5/3/2017
    
        Purpose: To execute sql scripts against a variety of servers.
    
        This script will take a list of servers and instances and then iterate
        over every database.  It has a section where you can query for whether
        a specific object exists.  If it exists, it will execute all the scripts
        in the specified directory.
    
        $SQLInstanceList - The full path and name of a text file containing the names of
            the instances to run against.  One entry per line, Ex: MyServerName\MyInstanceName
    
        $ScriptToRunDirectory - The full path to a directory containing the script file(s) that you want to use.
            It doesn't do recursion, but will pick up any .sql file in the directory and run it agains thte server.
            It does so in alphabetical order, so put numbers at the front of the scripts if execution sequence is important.
    
        $Query - This should be a query that will be run to determine if the rest of the scripts should be run or not.
            You should set it to return 0 if it's the wrong database and anything else if it's the right one.
            The example below determines if the current database (remember the script is stepping over every database)
            has the specified object.  Remember to specify the schema.
    
    #>
    
    # Modify the below items to the necessary values.
    $SQLInstanceList = "C:\Temp\SQLInstance.txt"
    $ScriptToRunDirectory = "C:\Temp"
    $Query = "SELECT ISNULL(OBJECT_ID('HumanResources.Department'), 0)"
    
    # You shouldn't need to modify anything below this line.
    ################################################################################################
    
    # For Each
    ForEach ($Instance In Get-Content $SQLInstanceList)
    {
    
        Write-Host "Connecting to: " $Instance
    
        [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null 
        $SMO = new-object ('Microsoft.SqlServer.Management.Smo.Server') $Instance
    
        ForEach ($Database In ($SMO.Databases))
        {
    
            Write-Host "Database: $($Database.Name)"
    
            #Test to make sure that we want to run it against this database.
            $Results = ($SMO.Databases[$Database.Name].ExecuteWithResults($Query)).Tables[0].Rows[0][0]
    
            if($Results -ne 0)
            {
    
                Write-Host " Database Matched Criteria"
    
                ForEach ($File In (Get-ChildItem -Path $ScriptToRunDirectory -Filter "*.sql") | Sort-Object $_.name)
                {
    
                    Write-Host "  - $($File.FullName)"
    
                    $Script = [System.IO.File]::ReadAllText($File.FullName)
                    Write-Host "  " $File.name 
                    $Database.ExecuteNonQuery($Script)      
    
                }
    
            } else {
    
                Write-Host " Database Skipped"
            }
    
        }
    
    }
    
    • 1
  4. Kevin3NF
    2017-05-04T05:39:58+08:002017-05-04T05:39:58+08:00

    当我需要在我的环境中接触多个数据库时,这听起来很像你的,我使用类似这样的东西来生成必要的语句......然后我将其复制并粘贴到一个新窗口以运行:

    Select '
    
    use '+[name]+'
    go
    
    --replace this with your create function statement
    Create View MyView
    AS
    Select * from sysobjects
    
    go
    '
    From master..sysdatabases where [name] like '%test%'
    

    使用文本运行此结果会产生:

    use Test
    go
    
    --replace this with your create function statement
    Create View MyView
    AS
    Select * from sysobjects
    
    go
    
    
    use Test2
    go
    
    --replace this with your create function statement
    Create View MyView
    AS
    Select * from sysobjects
    
    go
    
    • 1

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve