共计 11704 个字符,预计需要花费 30 分钟才能阅读完成。
[SQL Compare] 是一款比拟和同步 SQL Server 数据库构造的工具。现有超过 150,000 的数据库管理员、开发人员和测试人员在应用它。当测试本地数据库,暂存或激活近程服务器的数据库时,SQL Compare 将调配数据库的过程自动化。
下载 SQL Compare 试用版【慧都网】
Phil Factor 演示了如何应用 XML argfiles 将参数传递给 SQL Compare,从而打消了每个指标数据库所需的许多批改数据库模式比拟和部署过程所波及的繁琐脚本。
有很多办法能够应用 PowerShell 主动执行须要执行 SQL Compare 的许多惯例开发工作。您抉择的办法取决于您的要求。本文旨在指出从命令行界面(CLI)运行 XML 时,应用 XML 将具体指令传递给 SQL Compare 的一些长处。
**
命令行许可
**
须要在多台计算机上安装 SQL 比拟命令行的自动化程序须要 Redgate Deploy 或 SQL Toolbelt 许可证。无关残缺的详细信息,请参阅文档的“更改散发的命令行”页面。
将参数传递给 SQL Compare CLI
SQL Compare CLI 容许您从 XML 参数文件(argfile)或应用我的项目文件传递参数,以及在命令行尾部应用开关的更罕用办法。如果您须要大量参数但无奈从 GUI 生成我的项目文件,则此性能很有用。
应用 XML argfile 传递参数的起因有很多。主动生成我的项目文件不是一个好主见,而反对 XML argfile。这意味着您能够从头开始为每个工作创立 XML argfile,并能够按计划执行所有工作。您还能够应用 SQL Compare 有时须要的所有许多细节来执行个别工作,而只需填写更改的细节,例如服务器,数据库或凭据,而所有其余选项,开关等放弃不变。我在应用 Linux 或 Windows 上的 SQL Compare 命令行比拟和部署 SQL Server 数据库的文章中给出了所有这些阐明。
咱们能够总结这些办法的一些长处和毛病。
**
应用 PowerShell 的 XML 办法入门
**
当反复很多或应用大量命令行选项时,应用 XML argfile 为命令行界面指定参数特地有用。这是用于 SQL 比拟的简略 XML 参数文件(argfile):
<?xml version=”1.0″?>
<commandline>
<database1>FirstDatabase</database1>
<server1>SecondHostname</server1>
<database2>SecondDatabase</database2>
<server2>SecondHostname</server2>
</commandline>
这里是一个更简单的:
<?xml version=”1.0″ encoding=”UTF-8″?>
<commandline>
<sourcecontrol1 />
<version1>HEAD</version1>
<server2>TargetDBServer</server2>
<database2>TargetDB</database2>
<scriptsfolderxml>MyScriptFolderXml.sfx</scriptsfolderxml>
<migrationfolderxml>MyMigrationFolderXml.mfx</migrationfolderxml>
<include>Assembly</include>
<include>FullTextCatalog</include>
<include>Function</include>
<include>Schema</include>
<include>StoredProcedure</include>
<include>Table</include>
<include>View</include>
<include>identical</include>
<Synchronize />
</commandline>
将所有这些设置保留在 XML argfile 中之后,您能够从 Bash,PowerShell 或命令提示符处执行它:
sqlcompare /Argfile:MyXMLfilename.xml
如果执行此操作,则能够增加的惟一其余命令行开关是 /verbose 或 /quiet。其余的必须在 XML argfile 中。这给咱们带来了诸如明码之类的敏感信息的问题,这些信息咱们无奈存储在 XML argfile 中,因而咱们也无奈将其别离传递给 CLI。稍后,我将向您展现如何解决此问题,然而如果您应用命令提示符或 Bash,这依然是一个问题。
指定开关
开关能够以长或短的模式蕴含在其开关名称中,作为名称,其值作为 XML 值。如果您有多个值(例如在 /options 开关中容许的值),则能够将它们用逗号分隔:
<options> n,oc,t </ options>
创立示意开关的更简单的 argfile 键的最简略办法是检出等效的 SQL Compare 我的项目文件。我不晓得为什么两者之间的 XML 构造和键会有很大的不同,因为它们简直是并行的。也就是说,大多数乏味且简单的键都是雷同的,您能够在它们之间剪切和粘贴。这使您能够在 GUI 中进行沉重的工作,保留我的项目文件,并挑选出代表所需开关的所需位。
从哈希表中的参数列表创立 Argfiles
对我而言,在 PowerShell 中创立这些 XML argfile 的最简略办法是将参数放入哈希表中,并将其传递给帮忙函数以将其转换为正确的 XML 格局。它打消了手工制作 XML 的许多烦人的谬误。
<# Unless you like writing XML, the easiest way of creating these files in PowerShell is probably this. We just put our parameters into a hash table and pass it to a function.
#>
$MyParameters = @{
'Database1' = 'Sigrid';
'Server1' = 'MyFirstServer';
'Database2' = 'Sigrid'
'Server2' = 'MySecondServer';
'userName1' = 'MyUsername1';
'password1' = 'MyPassword1';
'userName2' = 'MyUsername2';
'password2' = 'MyPassword2';
'report' = "${env:temp}MyReport.html";
'force' = $null;
'reportType' = 'HTML';
'loglevel' = 'Warning';
'options' = 'default'
}
just a helper function to translate the hash table to the XML format expected
neither of the built-in cmdlets can cut it because they wrap the hash table up
Function SaveHashTableAsSQLCompareXML([hashtable]$TheHashTableParameters,[string]$WhereToStoreIt)
{
$xmlDoc = [System.Xml.XmlDocument]'<?xml version="1.0"?>';
$commandline = $xmlDoc.AppendChild($xmlDoc.CreateElement('commandline'));
$TheHashTableParameters.GetEnumerator() | foreach {$Element = $commandline.AppendChild($xmlDoc.CreateElement($_.Name));
if ($_.Value -ne $null) # if it is a switch with a parameter
{$textNode = $Element.AppendChild($xmlDoc.CreateTextNode($_.Value));
}
}
$xmlDoc.Save("$WhereToStoreIt"); #save it to the user temp area
}
SaveHashTableAsSQLCompareXML $MyParameters “${$env:temp}Paramfile.xml”
sqlCompare /Argfile:”${env:temp}Paramfile.xml” >”${env:temp}summary.txt”
start “${env:temp}MyReport.html” #display the HTML result report
用于惯例比拟工作的简略 Argfiles
这是一些用于各种工作的 argfile 示例。对于未加密的明码,读者会有些不解,但稍后再解决。
编写脚本的新版本
<?xml version=”1.0″?>
<commandline> <!– Script out a new version of the script folder –>
<database1>Sigrid</database1>
<server1>MyFirstServer</server1>
<userName1>MyUsername</userName1>
<password1>MyP@55w0rd</password1>
<makescripts>MyPathToTryout</makescripts>
<force/>
</commandline>
生成一个构建脚本
<?xml version=”1.0″?>
<commandline> <!– generate a build script –>
<database1>Sigrid</database1>
<server1>MyFirstServer</server1>
<userName1>MyUsername</userName1>
<password1>MyP@55w0rd</password1>
<empty2/>
<scriptFile>MyPathToMyScriptFile.sql</scriptFile>
<force/>
</commandline>
报告两个数据库之间的任何差别
<?xml version=”1.0″?>
<commandline> <!–report on any differences between two databases –>
<loglevel>Warning</loglevel>
<password1>MyP@55w0rd</password1>
<force />
<Server2>MyOtherServer</Server2>
<password2>MyP@55w0rd</password2>
<userName2>MyUsername</userName2>
<options>default</options>
<Server1>MyFirstServer</Server1>
<reportType>HTML</reportType>
<userName1>MyUsername</userName1>
<Database2>Sigrid</Database2>
<Database1>Sigrid</Database1>
<report>MyPathToMyReport.html</report>
</commandline>
编写并报告两个数据库之间的差别
<?xml version=”1.0″?>
<commandline>
<!– Script out, and report on, the differences between two databases –>
<loglevel>Warning</loglevel>
<password1>MyP@55w0rd</password1>
<force />
<Server2>MyOtherServer</Server2>
<password2>MyP@55w0rd</password2>
<userName2>MyUsername</userName2>
<options>default</options>
<Server1>MyFirstServer</Server1>
<reportType>HTML</reportType>
<userName1>MyUsername</userName1>
<database2>Sigrid</database2>
<database1>Sigrid</database1>
<exclude>Identical</exclude>
<scriptfile>MyPathToMyDatabaseBuild.sql</scriptfile>
<report>MyPathToMyReport.html</report>
</commandline>
从数据库创立快照
<?xml version=”1.0″?>
<commandline>
<!– make a snapshot of a database –>
<Server1>MyFirstServer</Server1>
<database1>Sigrid</database1>
<userName1>MyUsername</userName1>
<password1>MyP@55w0rd</password1>
<loglevel>Warning</loglevel>
<force />
<makesnapshot>MyPathToMyDatabase.snp</makesnapshot>
<options>default</options>
</commandline>
应用 XML argfile 执行 SQL Compare CLI
以下 1 -liner 将在 ArgFile 目录中执行所有 XML argfile:
<# now we can execute sql Compare CLI with all the argfiles #>
Get-ChildItem -Path “${env:temp}” -Filter ‘*.xml’|
foreach{SQLCompare “/Argfile:$($_.fullname)”}
动静生成 argfile
如果您没有任何 argfiles 怎么办?咱们能够即时生成它们!一旦存在 argfile,您就能够在每次要从新执行它时应用下面的一个划线。
这是咱们的第一个简略版本,可即时生成用于为每个提供的数据库制作快照的 argfile。只管它很好,然而如果您应用的是 SQL Server 身份验证而不是 Windows 身份验证,则存在未加密的明码问题,如果您应用的是 Linux 或 MacOS,则可能会呈现这种状况。
<# We just have a list of servers, databases and (in this case userids and passwords) #>
@(
@{
'Database' = 'Sigrid'; 'Server' = 'MyOtherServer';
'userid' = 'MyUsername'; 'password' = 'MyP@55w0rd' },
@{
'Database' = 'Abnego'; 'Server' = 'MyOtherServer';
'userid' = 'MyUsername'; 'password' = 'MyP@55w0rd' },
@{
'Database' = 'Antipas'; 'Server' = 'MyOtherServer';
'userid' = 'MyUsername'; 'password' = 'MyP@55w0rd' },
@{
'Database' = 'Archaelus'; 'Server' = 'MyOtherServer';
'userid' = 'MyUsername'; 'password' = 'MyP@55w0rd' },
@{'Database' = 'Adeliza'; 'Server' = 'MyFirstServer'},
@{'Database' = 'Sigrid'; 'Server' = 'MyFirstServer'}
) | foreach{
"<?xml version=""1.0""?>
<!– make a snapshot of a database $($_.Database) on $($_.Server) –>
<commandline>
<Server1>$($_.Server)</Server1>
<database1>$($_.Database)</database1>
$(if ($_userid -ne $null)
{"<userName1>$($_.userid)</userName1>
<password1>$($_.password)</password1>”
})
<loglevel>Warning</loglevel>
<force />
<makesnapshot>${env:temp}$($_.Database)-$($_.Server).snp</makesnapshot>
<options>default</options>
</commandline>
“>”${env:temp}Snap-$($_.Database)-$($_.Server).xml”
}
<# now we can execute sql Compare CLI with all the argfiles #>
Get-ChildItem -Path “${env:temp}” -Filter ‘Snap*.xml’ |
foreach{SQLCompare “/Argfile:$($_.fullname)” }
忽然之间,咱们当初有了很多快照,还有一种将实时数据库与快照进行比拟的办法,使咱们可能确定更改了哪些内容,而后兴许能够用来保留这些更改。
明码存储问题
如前所述,许多读者会为将未加密的明码放入文件中而少见多怪。这总是一个坏主意。好的,将它们保留在您的用户区域中,以便取得 NTFS 访问控制所提供的保护措施。然而,明码也必须加密。
实际上,如果您齐全应用 SQL Server 身份验证,那么您的 SQL Compare 我的项目文件也应存储在您的用户区中(在 PowerShell 中,“${env:temp}”是指您用户区中的长期目录)。这是因为,只管明码是在我的项目文件中加密的,但这样做的形式是,无论 Windows / Linux 身份如何,任何人都能够应用加密的明码,并且他们能够粘贴到其我的项目文件中以应用 SQL 拜访数据库。
要存储凭据,Microsoft 倡议在 PowerShell 中应用 Import-CliXml 和 Export-CliXml。该 Export-Clixmlcmdlet 应用 Windows 数据保护 API 加密凭据对象。加密可确保只能通过您的用户帐户以及仅在该计算机上解密凭据对象的内容。导出的 CLIXML argfile 不能在其余计算机上或该计算机上的其余用户应用。请参阅应用 PowerShell 在磁盘上平安存储凭据和应用 PowerShell 平安明码:加密凭据。
这是如何在磁盘上存储明码的示例。我只想列出无关服务器上我的数据库的所有详细信息,并且我心愿有一个例程能够平安地执行此操作,而不论我应用的是 Windows 身份验证还是 SQL Server 身份验证:
import-Module sqlserver #import all the libraries for SMO
$SQLserver = ‘MyFirstServer’
$SqlUserName = ‘MyUsername’
if ($SqlUserName -ne $null)
{
$SqlEncryptedPasswordFile = `
“$env:USERPROFILE$($SqlUserName)-$($SQLserver).xml”
test to see if we know about the password in a secure string stored in the user area
if (Test-Path -path $SqlEncryptedPasswordFile -PathType leaf)
{
#has already got this set for this login so fetch it
$SqlCredentials = Import-CliXml $SqlEncryptedPasswordFile
}
else #then we have to ask the user for it (once only)
{
#hasn't got this set for this login
$SqlCredentials = get-credential -Credential $SqlUserName
$SqlCredentials | Export-CliXml -Path $SqlEncryptedPasswordFile
}
$ServerConnection = new-object `
"Microsoft.SqlServer.Management.Common.ServerConnection" `
('MyFirstServer', $SqlCredentials.UserName, $SqlCredentials.Password)
}
else
{
$ServerConnection =
new-object "Microsoft.SqlServer.Management.Common.ServerConnection" `
($csb.server)
}
$s = new-object (“Microsoft.SqlServer.Management.Smo.Server”) $ServerConnection
$s.Databases
SQL Compare argfiles 的问题在于命令行界面通过 CLI 间接从磁盘读取它们,并且咱们不容许将敏感信息(例如明码)作为参数独自传递。这意味着必须在产品中解决在 argfile 中以纯文本格式存储明码的问题。
在 Argfiles 中存储明码的解决方案
为了疾速解决此问题,并为 SQL Compare 的现有用户提供解决方案,咱们蠢笨地增加了“即时”明码。
让咱们从那些 argfiles 从新开始。咱们当初不打算在其中输出明码。如果他们有用户名,那么咱们须要即时增加适当的明码,以创立 XML argfile 的长期版本,而后将其传递给 SQL Compare。它能够用于 username1or username2,也能够用于 password1or password2。
<# We just have a list of servers, databases and (in this case Userids and logins) #>
@(
@{'Database' = 'Sigrid'; 'Server' = 'MyOtherServer'},
@{'Database' = 'Abednego'; 'Server' = 'MyOtherServer'},
@{'Database' = 'Antipas'; 'Server' = 'MyOtherServer'},
@{
'Database' = 'Archaelus'; 'Server' = 'MyOtherServer';
'userid' = 'MyUsername'
},
@{
'Database' = 'Adeliza'; 'Server' = 'MyFirstServer';
'userid' = 'MyUsername'
},
@{
'Database' = 'Sigrid'; 'Server' = 'MyFirstServer';
'userid' = 'MyUsername'
}
) | foreach{
"<?xml version=""1.0""?>
<!– make a snapshot of a database $($_.Database) on $($_.Server) –>
<commandline>
<Server1>$($_.Server)</Server1>
<database1>$($_.Database)</database1>
$(if ($_.userid -ne $null)
{"<userName1>$($_.userid)</userName1>
<password1>$($_.password)</password1>”
})
<loglevel>Warning</loglevel>
<force />
<makesnapshot>${env:temp}$($_.Database)-$($_.Server).snp</makesnapshot>
<options>default</options>
</commandline>
“>”${env:temp}Snap-$($_.Database)-$($_.Server).xml”
}
当初,咱们必须创立一个帮忙函数来获取明码。首次对任何用户和服务器运行此性能时,都会从您那里获取明码,并且您必须输出该明码。尔后,它将从平安存储中获取该明码。
function SavedPassword ($SqlUserName, $server)
{
$SqlEncryptedPasswordFile = `
"$env:USERPROFILE$($SqlUserName)-$($server).xml"
test to see if we know about the password in a secure string stored in the user area
if (Test-Path -path $SqlEncryptedPasswordFile -PathType leaf)
{
#has already got this set for this login so fetch it
$SqlCredentials = Import-CliXml $SqlEncryptedPasswordFile
}
else #then we have to ask the user for it (once only)
{
#hasn't got this set for this login
$SqlCredentials = get-credential -Credential $SqlUserName
$SqlCredentials | Export-CliXml -Path $SqlEncryptedPasswordFile
}
$SqlCredentials.GetNetworkCredential().password
}
当初,咱们从新营业。可悲的是,它在代码中有点简单,但这丝毫不会减慢速度。咱们顺次提取每个 argfile,对其进行对等以查看其是否须要明码,如果须要,请插入明码。咱们将每个正本复制到一个新的临时文件,并将其传递给 SQL Compare。应用它后,咱们会立刻将其删除!
Get-ChildItem -Path “${env:temp}” -Filter ‘Snap-*.xml’ |
foreach{
$content = [System.IO.File]::ReadAllText($_.fullname);
$xmlContent = $content
write-output "$($xmlContent.'#comment')"
$server1 = $xmlContent.commandline.server1
$server2 = $xmlContent.commandline.server2
$username1 = $xmlContent.commandline.username1
$username2 = $xmlContent.commandline.username2
if ($username1 -ne $null)
{$xmlContent.commandline.password1 = (SavedPassword $username1 $server1)
}
if ($username2 -ne $null)
{$xmlContent.commandline.password2 = (SavedPassword $username2 $server2)
}
$Tempfile="${env:temp}Temp_$($_.basename).xml"
$xmlContent.Save($Tempfile)
SQLCompare "/Argfile:$Tempfile"
Remove-Item -Path "$Tempfile"
}
论断
我最喜爱应用 argfiles 将参数传递给 SQL Compare 的中央是,您能够通过将特定工作所需的所有 argfile 收集到一个目录中,而后顺次将每个 argfile 传递给 SQL Compare 来实现很多工作。它省去了很多脚本,意味着您能够通过增加,批改或删除 argfiles 来批改整个工作。与我的项目文件不同,这些 XML argfile 能够通过脚本或在文本编辑器中轻松批改。
如前所述,如果您抉择应用 argfiles 并应用 PowerShell,则须要解决未加密明码的问题。
想要购买正版受权,或理解更多产品信息【征询慧都在线客服】]