SQL Compare教程:在Argfiles中使用SQL Compare命令行(下)

本文演示了如何使用XML argfiles将参数传递给SQL Compare,从而消除了每个目标数据库所需的许多修改数据库模式比较和部署过程所涉及的繁琐脚本教程的后半部分内容——使用XML argfile执行SQL Compare CLI、动态生成argfile、密码存储问题。

SQL Compare是一款比较和同步SQL Server数据库结构的工具。现有超过150,000的数据库管理员、开发人员和测试人员在使用它。当测试本地数据库,暂存或激活远程服务器的数据库时,SQL Compare将分配数据库的过程自动化。

SQL Compare试用版

本文演示了如何使用XML argfiles将参数传递给SQL Compare,从而消除了每个目标数据库所需的许多修改数据库模式比较和部署过程所涉及的繁琐脚本。本文是后半部分内容,介绍了使用XML argfile执行SQL Compare CLI、动态生成argfile、密码存储问题。

使用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{    "<ml version=""1.0""gt;<!-- 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 Compare访问数据库。

要存储凭据,Microsoft建议在PowerShell中使用Import-CliXml和Export-CliXml。Export-Clixmlcmdlet使用Windows数据保护API加密凭据对象。加密可确保只能通过您的用户帐户以及仅在该计算机上解密凭据对象的内容。导出的CLIXML argfile不能在其他计算机上或该计算机上的其他用户使用。

这是如何在磁盘上存储密码的示例。我只想列出有关服务器上数据库的所有详细信息,并且我希望有一个例程可以安全地执行此操作,而不管我使用的是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。它可以是username1或 username2,也可以是password1或 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{    "<ml version=""1.0""gt;<!-- 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来完成很多工作。它削减了很多脚本,意味着您可以通过添加、修改或删除argfile来修改整体任务。与项目文件不同,这些XML argfile可以通过脚本或在文本编辑器中轻松修改。

如前所述,如果您选择使用argfiles并使用PowerShell,则需要解决未加密密码的问题。

本教程内容到这里就结束了,喜欢的朋友可以继续关注我们,了解更多相关文章资讯!您也可以SQL Compare试用版体验一下~

相关内容推荐:

SQL Compare教程:在Argfiles中使用SQL Compare命令行(上)


想要购买SQL Compare正版授权,或了解更多产品信息请点击“咨询在线客服”

850×682.png

标签:

来源:慧都

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年9月27日
下一篇 2019年9月27日

相关推荐

发表回复

登录后才能评论