我最终想使用 PowerShell 来替换我们用于 SQL 实例监视器的旧 KornShell 脚本。但是,我很难让我的大脑围绕 PowerShell 实际与 SQL Server 通信的所有不同方式。不确定这是否是全部,但我可以通过以下 5 种完全不同的方式查询 SQL 服务器的版本:
1. SQLConnection .NET 类
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=MyServer;Database=Master;Integrated Security=True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "Select @@version as SQLServerVersion"
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
$DataSet.Tables[0]
Run Code Online (Sandbox Code Playgroud)
2. WMI 提供程序
$sqlProperties = Get-WmiObject
-computerName "MyServer"
-namespace root\Microsoft\SqlServer\ComputerManagement10
-class SqlServiceAdvancedProperty
-filter "ServiceName = 'MSSQLSERVER'"
$sqlProperties.VERSION
Run Code Online (Sandbox Code Playgroud)
3. SMO
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | Out-Null
$smo-var = New-Object …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 SQLCMD 实用程序通过 PowerShell 访问我计算机上的“localdb\MSSQLLocalDB”服务器。我使用的是 PowerShell v5、.NET v5.0,服务器名称是(localdb)\MSSQLLocalDB我在 Microsoft SQL Server Management Studio 2014 中连接到它时的名称。
PS C:\> sqlcmd -S localdb\MSSQLLocalDB并PS C:\> sqlcmd -S .\localdb\MSSQLLocalDB导致此错误:
Sqlcmd:错误:Microsoft ODBC Driver 11 for SQL Server:SQL Server 网络接口:定位服务器/实例时出错 [xFFFFFFFF]。
我在 Management Studio 中查询服务器名称SELECT @@ServerName并-S在上面的命令之后使用它并得到相同的错误。
PS C:\> sqlcmd -S localdb 给出这个错误:
Sqlcmd:错误:用于 SQL Server 的 Microsoft ODBC 驱动程序 11:命名管道提供程序:无法打开与 SQL Server 的连接 [53]
其他注意事项:我能够连接到服务器并使用此连接字符串在 C# 控制台应用程序中使用名为testdb01的数据库System.Data.SqlClient:
"Data Source=(localdb)\\mssqllocaldb;Initial Catalog=testdb01;Integrated Security=SSPI;"
Run Code Online (Sandbox Code Playgroud) 在我的新工作中,我们在每台服务器上都有多个命名实例。例如
我在工作中有一个 SQL PowerShell 脚本,它调用操作系统,调用Foo.exe但需要传递命令行参数(连接字符串)。每个实例上都将存在一个 SQL 代理作业,带有 PowerShell 类型的步骤,需要知道当前上下文是什么。即此执行在 DevIntegrated 上开始。
我不想让每个脚本都以...开头
$thisInstance = "Dev"
Run Code Online (Sandbox Code Playgroud)
...特别是因为当我们在接下来的几个月中迁移到环境(新服务器和命名实例)时,我必须对其进行编辑。
如果我启动 SQLPS,我可以通过切片和切块 Get-Location 的结果或运行来确定我的实例
(Invoke-Sqlcmd -Query "SELECT @@servername AS ServerName" -SuppressProviderContextWarning).ServerName
Run Code Online (Sandbox Code Playgroud)
当 SQL 代理启动 PowerShell 类型的作业时,它会在 C:\windows\system32 中启动,并且Get-Location路由不起作用,因为它不在 SQLSERVER 上下文中。我可以切换到该上下文,但我将处于 SQL Server 的“根”,并且不知道我应该在哪个实例中。Invoke-Sqlcmd出于相同的原因,使用该路由也不起作用(从技术上讲,它在那里超时不是默认实例)
据我所知,我已经列举了我可以进入工作日志的所有基本“事情”,但似乎没有任何显示 SQLSERVER:\SQL\Server1\DevIntegrated
Get-ChildItemGet-HostGet-LocationGet-ProcessGet-PSDriveGet-PSProviderGet-ServiceGet-TraceSourceGet-VariableGet-Process似乎我可以使用它和一些尝试通过击中实例和匹配 spid 来拼凑东西的巫术,但这听起来像是来自地狱的血腥黑客。一定有一些基本的东西我错过了,有人能解释一下吗?
我曾调查过使用其他工作类型,但没有得到令人满意的解决方案。研究表明,SQL 代理下列出的 PowerShell 是 SQLPS,通过右键单击代理启动它的实例会自动将我放到正确的位置。只有当我将交互式代码粘贴到作业步骤中时,我才知道前面提到的差异。
操作系统的作业类型使我处于相同的状态,因为我找不到确定哪个实例将我放入命令外壳的方法。当然,我可以使用 sqlcmd 并获取 的值,@@servername …
我有一个中央数据库,我将所有服务器上的作业结果写回。我通过 SQL 作业中的 powershell 将 3 个参数传递回中央服务器上的 sp 验证作业应该在当时运行等。然后通过 SSRS 公开信息,以便我们可以看到作业失败/长时间运行的作业/ & 尚未运行但应该运行的作业(或者如果有人搞砸了时间表)。
为此,我在每台服务器上的每个作业中添加了 2 个作业步骤,并且我想将脚本减少到每个作业中仅添加 1 个步骤……甚至可能从网络共享中调用它。
但我的问题是我传递的 3 个参数之一。我需要从正在执行的作业中获取正在执行的作业 ID 或作业名称,因此我不必对名称参数进行硬编码。我传递的 3 个参数是 jobid、status(success/fail)、errormsg。我编写的 powershell 脚本非常简单。
Invoke-sqlcmd -ServerInstance "MYRemoteSYSTEM" -Database remoteDB -Query "exec dbo.JOB_LOG 'JOBNAME/ID','Success/FAIL','BAD MESSAGE HERE'"
这将我需要的东西写到桌子上。我查看了 msdb.dbo.sp_help_job / msdb.dbo.sp_get_composite_job_info / dbo.xp_sqlagent_enum_jobs / 但这些都不能保证在有超过 1 个作业在执行的情况下我得到正确执行作业的 ID 或名称同时。
我什至尝试查看 sys.sysprocesses,但我认为由于代理作业是一个 powershell 脚本,它显示为“.Net SqlClient 数据提供程序”,因此我无法从显示为“SQLAgent - TSQL JobStep (Job 0xF1800243164745429C30474FFD5C990C : Step 1)”---这是我从Denny Cherry 的帖子中学到的- 谢谢 Denny-
任何关于如何获取正在执行的 jobid 的想法将不胜感激。
谢谢,
克里斯
我的任务是发现在我们的域中运行的所有 SQL Server 实例。在某些情况下,每个服务器有多个实例。我见过两种不同的 PowerShell 方法来查找这些实例,但似乎都没有找到所有实例。
1) 使用 WMI
$srvr = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer $computerName
$instances = $srvr | ForEach-Object {$_.ServerInstances} | Select @{Name="fullName";Expression={$computerName +"\"+ $_.Name}}
return $instances
Run Code Online (Sandbox Code Playgroud)
2)使用远程注册表(与 Get-SQLInstance 1 一样)
我遇到的最大问题是,并非我所知道的所有服务器都使用 SQL Server WMI 提供程序运行,也不是所有服务器都允许远程注册。有没有第三种方法?我可以使用远程桌面访问所有服务器,但我正在查看大约 30 台机器,并希望尽可能避免手动步骤。这仅需要适用于 SQL Server 2008 及更高版本,虽然了解其他 SQL Server 服务 (SSIS/SSAS/SSRS) 会很好,但我主要关注 SQL Server 本身。
我们的 DBA 团队不会使用以下方法验证备份TSQL(备份后可以轻松完成并且几乎不需要时间,所以我不明白为什么不这样做):
RESTORE VERIFYONLY
FROM DISK = 'D:\Backups\LOCATION'
Run Code Online (Sandbox Code Playgroud)
他们过去曾遇到过问题,所以即使我们认为他们会从中吸取教训,但他们没有。我创建了一个 Powershell 脚本来执行此操作,因为我们有大约 100 多台服务器,我只想针对所有备份运行此脚本,以确保它们有效。下面的脚本运行正确(因为它不会中断或抛出错误),我很好奇是否有办法在 Powershell 中取回我们通常会在 SSMS 中获得的打印消息,其中说明文件 1 上的备份集是作为验证有效。
$SqlCon = New-Object System.Data.SqlClient.SqlConnection
$SqlCon.ConnectionString = "SERVER=SERV\INST;Integrated Security=true;DATABASE=master"
$baks = Get-ChildItem "D:\Backups\" -Filter *.BAK
foreach ($bak in $baks)
{
$SqlCon.Open()
$cd = New-Object System.Data.SqlClient.SqlCommand
$cd.Connection = $SqlCon
$cd.CommandText = "RESTORE VERIFYONLY FROM DISK = @f"
$cd.Parameters.Add("@f", $bak.FullName)
$cd.ExecuteNonQuery()
$SqlCon.Close()
}
Run Code Online (Sandbox Code Playgroud) 我在未运行的 SQL 代理作业步骤中设置了以下代码。收到的消息很简单:
无法开始执行第 1 步(原因:第(46)行:语法错误)。步骤失败。
工作的持续时间是: 00:00:00
此脚本的第 46 行是here-string:
,@DriveLetter = '$($c.DriveLetter)'
Run Code Online (Sandbox Code Playgroud)
此脚本在 SQL Server 代理之外完美运行。
服务器名称表:
CREATE TABLE ServerTable (
ServerName varchar(50)
)
Run Code Online (Sandbox Code Playgroud)
磁盘空间表类似于:
CREATE TABLE DiskSpace (
ID int IDENTITY(1,1),
ServerName varchar(50),
DriveLetter varchar(2),
DiskSpaceCapacityGB decimal(12,5),
DiskSpaceFreeGB decimal(12,5)
)
Run Code Online (Sandbox Code Playgroud)
PowerShell 脚本:
This command is to allow SQL Agent job to show failure in event PowerShell script errors
Default behavior in SQL Agent for PowerShell steps it 'Continue'
$erroractionpreference = "Stop"
$sqlInstance = 'server1'
$sqlDatabase …
Run Code Online (Sandbox Code Playgroud) 我知道有一些问题可以解决数据库卡在RESTORING状态的问题,并且已经使用这些解决方案手动使数据库重新联机,但我的情况有些不同。
我使用 Powershell 脚本进行自动恢复,该脚本将生产副本恢复到 DEV 实例。脚本大约一年没有变化,偶尔恢复过程完成但恢复的数据库卡在RESTORING状态(有时脚本工作正常,有时会像这样失败)。
每次如果我手动重新运行该过程,它就会工作,或者如果我从 SSMS 的用户界面或通过 T-SQL 手动恢复数据库,它都会毫无问题地完成。
我找到了建议CHECKDB在恢复的数据库上运行的答案,但没有发现导致此问题的原因。
由于恢复脚本恢复了数据库的完整备份并使用了一个"WITH RECOVERY"选项,我试图找出可能会停止恢复过程的原因,尽管我实际上是使用"WITH RECOVERY".
任何建议都非常感谢,因为我一直试图理解为什么会不时发生这种情况。
我很想解决问题的根本原因而不是治标,即再次手动恢复数据库。
更新:
正如@Brent 推荐的那样,Github Gist在这里。
我有足够的 PowerShell 技能来开始工作,但没有使用 SQL 服务器。有人可以指出我如何使用 PowerShell 获取有关远程 SQL 服务器的信息以识别其上运行的数据库的正确方向。
谢谢你的帮助。
编辑 - 使用 SMO 代码
我试图将这段代码放在一起,但得到错误:找不到类型 [Microsoft.SqlServer.Management.Smo.Server] 确保加载了包含此类型的程序集
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$sqlServer = New-Object("Microsoft.SqlServer.Management.Smo.Server") "MSQLULTDBS04"
foreach($sqlDatabase in $sqlServer.databases) {$sqlDatabase.name}
Run Code Online (Sandbox Code Playgroud) 我有一些 SQL Server 机器无法连接到任何外部站点。
我在管理数据库时越来越多地使用 PowerShell,所以我肯定需要安装这个模块,以便我可以使用我的 PowerShell 例程。
事实证明,在这些离线机器上安装 SQL Server 模块很困难。
当我尝试安装模块时:
该SqlServer模块要求提供NuGet 模块包:
然后我得到了这片红色字母的海洋和以下错误消息,如下图所示:
警告:无法从 URI“ https://go.microsoft.com/fwlink/?LinkID=627338&clcid=0x409 ”下载到“”。
警告:无法下载可用提供程序的列表。检查您的互联网连接。PackageManagement\Get-PackageProvider:无法找到包提供程序“NuGet”。
它可能尚未导入。尝试“Get-PackageProvider -ListAvailable”。
在 C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:7415 char:30 + ... tProvider = PackageManagement\Get-PackageProvider -Name $script:NuGet ...
此 PowerShell 模块安装的解决方法是什么?
powershell ×10
sql-server ×8
automation ×1
backup ×1
installation ×1
monitoring ×1
patching ×1
smo ×1
sqlcmd ×1