[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 = [xml]$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,则须要解决未加密明码的问题。
想要购买正版受权,或理解更多产品信息【征询慧都在线客服】]
发表回复