我们目前有3个网络产品。除品牌外,所有3种产品几乎完全相同(针对不同行业的垂直化)。目前,由于后勤需求,我们有3个独立的 - 几乎相同的 - 数据库(我们称之为数据库A,数据库B和数据库C)。我们需要将数据库分开以进行数据隔离(这是一个不可协商的问题)。
我们当前更新,创建,删除存储过程的工作流程是在其中一个数据库中执行,然后将“使用数据库A”更改为“使用数据库B”并单击运行,然后对数据库C进行相同操作。使所有三个数据库上的存储过程相同。这不是太糟糕,但我们面临一个新问题。
我们现在有一些高级公司客户希望“白标”我们的产品,并拥有自己的数据库来分别存储他们的数据。我们可以以同样的方式做到这一点,但最终有足够的数据库,这将是非常麻烦。
有没有办法让一个数据库保存所有存储过程并让它们与那些与所谓的过程数据库相关的表进行交互?我知道我可以在主表中创建SP_程序,并为它们提供数据库名称参数,然后将其注入动态SQL,但我不想将所有存储过程转换为动态SQL(有很多它们和我我不喜欢使用动态SQL。或者,有没有办法自动化将所有存储过程更改应用到所有数据库的过程?
答案 0 :(得分:0)
处理"一遍又一遍地运行完全相同的脚本的最佳方式"在不同的服务器/数据库上是熟悉sqlcmd.exe的处理方式。
把它放在文件中:
set __sqlcmdexe=C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE
set __sqlcmdexe=C:\Program Files\Microsoft SQL Server\110\Tools\Binn\SQLCMD.EXE
"%__sqlcmdexe%" -S Server001\Instance001-i .\MyVersionSample.sql -o MyOutput_Server001_Instance001_Northwind.txt -v MyDatabaseName="Northwind" FavoriteColor="Red" MyErrorLog="MyErrorLog001.txt"
"%__sqlcmdexe%" -S Server001\Instance001-i .\MyVersionSample.sql -o MyOutput_Server001_Instance001_DoesNotExistDB.txt -v MyDatabaseName="DoesNotExistDB" FavoriteColor="Green" MyErrorLog="MyErrorLog002.txt"
set __sqlcmdexe=
调整值" Server001"和" Instance001" (实例名称,如果适用)以匹配环境中的内容。我使用" Northwind"作为真正的数据库名称。输入您拥有的一些(真实)数据库名称。 显然,请确保您的计算机上有正确的sqlcmd.exe路径。
把它放进去:
/*
: s e tvar MyDatabaseName "Northwind"
*/
:Error $(MyErrorLog)
Use [$(MyDatabaseName)]
GO
print 'You passed in a variable'
print '$(FavoriteColor)'
print ''
IF NOT EXISTS (SELECT name FROM master.sys.databases WHERE name = N'$(MyDatabaseName)')
BEGIN
print 'Database does not exist!!'
print '$(MyDatabaseName)'
print ''
END
Select @@VERSION
GO
这个简单的例子是Select @@ Version。相当温和。但它会证明。
您现在可以获得一些日志文件。也许是一个错误文件。
基本上,它将对您在bat文件中设置的环境和数据库反复运行相同的脚本。你得到一些日志文件。
.sql本身必须是" sqlcmd"' ish。这不是很多工作。
在测试脚本时,如果你去"查询:SqlCmdMode" (其中Query是一个菜单项,如"文件和编辑" ....您可以进入sqlcmd模式。
请注意,在我的示例中,您将看到此代码。
/*
: s e tvar MyDatabaseName "Northwind"
*/
如果你取消注释并取出一些空格,那么就这样做:
:setvar MyDatabaseName "Northwind"
(提醒你需要在sqlcmdMODE中)..你现在可以测试你的脚本了。
警告:如果在代码中设置了某些内容,它将使用-v标志覆盖从.bat文件传入的值。 这在此处记录:
这就是为什么我都注释掉了那个部分,并在:servar中添加了一些空格,以确保它不会覆盖通过-v开关传入的值。
Boo to microsoft没有修复它。
但这是一遍又一遍地执行相同脚本的最佳方式。一些简单的日志文件。 (IMHO)。
我有一个项目,我必须创建24个数据库(相同的DDL /架构)与文件组,文件,很多东西............我能够在几分钟内将它们甩出来。 .....使用这个系统。以及那些没有用的东西的日志文件。
这是获得可预测结果的好方法......而且不会意外遗漏某些东西。
祝你好运。答案 1 :(得分:0)
我们将SP源存储在源代码控制(TFS)中,并编写一些脚本来根据可调整的标准提取SP,然后将它们一起附加到文件中,以便应用于所选的数据库。我有理由相信更多的元工作会让我们设置服务器&数据库信息将它们应用于一组数据库而不需要干预,至少只要一切都编译好就可以了。
有像Red Gate这样的第三方工具(我从未使用过它们),它们将为您提取架构并准备脚本文件。所以你理论上可以保持一个主模式"数据库并使用那种东西来提取其他地方的应用程序的当前状态。
答案 2 :(得分:0)
就个人而言,我更喜欢TFS解决方案,我们自己在工作中使用它。
但是,如果你真的想在master数据库中使用存储过程(我建议反对),那么用sp_命名你的proc只是解决方案的一部分。另一部分是在当前数据库的上下文中运行proc。为此,您必须将过程标记为系统对象。
以下是如何操作:
use master
go
create procedure dbo.sp_test
as
select db_name()
select * from Sales.SalesOrderHeader
go
EXEC sys.sp_MS_marksystemobject sp_Test
GO
use AdventureWorks2012
go
exec sp_test
go
use master
go
drop procedure sp_test
go
请记住,它不受支持。但OTOH可能非常方便:)
答案 3 :(得分:0)
像DaveE建议的那样,将您的存储过程保留在版本控制中。这只是一种很好的做法。
如果您想一次更新多个目标,以下是一些建议:
1)在SSMS中使用已注册的服务器。可以将每个目标数据库创建为服务器组中的已注册服务器。然后,您可以右键单击服务器组并选择“新建查询”。此查询将针对组中的所有已注册服务器执行。 This is explained in detail on MSSQLTips
2)SQL Multi Script是我们在Red Gate开发的专用工具,以满足此用例。