我想我刚刚找到了 SQL Server SMO 和 PowerShell 最酷的东西。我被要求编写一个脚本来查找 SQL Server 实例中每个对象的所有者。我在 Technet/MSDN SQL Server 库上找到了一个脚本,但认为使用 PowerShell 获取它会容易得多,并且能够一次访问网络上的所有实例。
在玩的过程中,我在 Database 类中遇到了这个方法:Discover()
因此,如果您使用此代码:
#Load SMO
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') | Out-Null
$srv = New-Object 'Microsoft.SqlServer.Management.Smo.Server' "your instance name"
$db = $srv.Databases
$db.Discover()
Run Code Online (Sandbox Code Playgroud)
当你运行最后一行时,如果你连接到一个有很多数据库的实例,你会看到你的控制台开始滚动文本,就像它在药物上一样。
好吧,我去做了 $db | gm ,它几乎向您展示了 SMO 对象中可用的每个 TypeName。
现在我的问题。我可以执行$db.Discover() | Select Name, Owner,它将开始吐出带有名称和所有者值的所有内容。
我怎样才能获得返回对象的对象类型(比如它是触发器、模式、表等)?到目前为止,我似乎无法弄清楚。
编辑
到目前为止,我发现它似乎只能在数据库级别“发现”事物。显然,我在控制台缓存中的某个地方设置 $db了类似$db = ($srv.Databases).Item("aDatabase"),因为这是您可以调用该方法的唯一方法。尽管如此,仍在寻找一种方法来提取对象名称、类型和所有者。
我正在使用 Powershell 脚本来更新故障转移集群中命名 SQL 实例上的服务帐户。我正在尝试使用 SMO 和 WMI 来更新它,以便我可以更新主动节点上的服务帐户并将其填充到其他被动节点(如果我在配置工具中手动更新会发生这种情况)。我正在尝试在本地机器上执行脚本但更新远程服务器。根据我的 Google 搜索,我看到的错误似乎与安全相关,如果我在远程计算机上以提升的权限(以管理员身份)本地运行脚本,则该错误会成功。
编码:
[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.SqlWmiManagement") | Out-Null
$mc=New-Object -TypeName Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer "SQLHOST01"
$srvcs= $mc.Services | Where {$_.name -like "*INSTANCE01*"} | Where {$_.Type -like "Sql*"}
$srvcs | ft name,servicestate,serviceaccount
foreach ($s in $srvcs){
$s.SetServiceAccount("FOO\Bar","strongpass")
}
Run Code Online (Sandbox Code Playgroud)
错误:
Exception calling "SetServiceAccount" with "2" argument(s): "Set service account failed. "
At line:11 char:5
+ $s.SetServiceAccount("FOO\Bar","strongpass")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FailedOperationException
Run Code Online (Sandbox Code Playgroud)
使用:Windows 2008 R2(远程)SQL 2008 R2(远程)Windows 7 with SQL 2012 …
测试SQL服务器作业在执行Powershell脚本时挂起。它确实使用我的登录名和Powershell窗口工作,但不使用Agent帐户和工作。该SQL Agent用户具有读/写/执行权限与PowerShell脚本的目录。
例子:
Run as: SQL Server Agent Service Account
powershell.exe -file \\Server02\test2\Test.ps1
Run Code Online (Sandbox Code Playgroud)
代理帐户也已获得访问权限。
这个测试文件目前做了一些非常基本的事情:显示一个字符串。
当它运行时,它不会显示错误消息,因为它只是不响应。您知道发生了什么,或者缺少哪些安全设置吗?
我有一个 SQL Server 代理作业,它在一个步骤中调用 PowerShell 脚本。我想将 SQL 服务器名称和当前作业 ID 传递给我的脚本。
有了工作 ID,我没有问题。但是使用服务器名称...
我的 PowerShell 调用如下所示:
.\StopServices.ps1 -ServerName $(ESCAPE_DQUOTE(A-SVR)) -JobId $(ESCAPE_DQUOTE(JOBID))
Run Code Online (Sandbox Code Playgroud)
作业 ID 工作正常,但服务器名称为空。
如何将服务器名称传递给我的 PowerShell 脚本?
我有一个备份 SSAS 数据库的程序。
这是一种魅力。
现在我的服务器被 SSAS 备份填满,我想删除超过 2 天的备份文件。
为了实现这一点,我使用了以下 POWERSHELL 脚本:
#-------------------------------------------------------------------------------
# Script to delete old SSAS backup files
#
# Marcelo Miorelli
#
# 19-novembre-2014 Wed
#-------------------------------------------------------------------------------
#-- connect to the remote server -- SQLBILON1
#
ENTER-PSSESSION sqlbilon1
#-- set the Path where the backup files (.abf) are located
#
$path = 'H:\SQLBackups'
#-- set the number of days backups should be deleted -- in this case 2
#
$NumberOfDays = 2
#-- …Run Code Online (Sandbox Code Playgroud) 我正在运行以下简单的 Powershell 命令。
$Server = New-Object ('Microsoft.SqlServer.Management.Smo.Server') 'SerName'
$Server | SELECT *
Run Code Online (Sandbox Code Playgroud)
对于 FCI 集群,该ClusterName值始终为空,并且ClusterQuorumState和ClusterQuorumType始终为NotApplicable。 IsClustered虽然设置为 True。
如果我针对可用性组运行它,我会返回集群名称和其他两个属性的正确值。
Powershell 中有没有办法获取 FCI 实例的集群名称?我可以使用另一个 cmdlet?
我有一个代理作业,通常由 WMI 事件触发。该作业中有一个令牌,它会自动从 WMI 事件中获取一个值并将其替换为该步骤的 Powershell 代码,例如:
$alert_wmi_state = '$(ESCAPE_SQUOTE(WMI(State)))';
Run Code Online (Sandbox Code Playgroud)
SQL 代理配置为选中所有作业响应警报设置的替换令牌,因此,当 WMI 事件触发时,替换会正常发生,并且运行的代码为:
$alert_wmi_state = '7';
Run Code Online (Sandbox Code Playgroud)
但是,该作业有可能手动运行(即右键单击,在步骤中启动作业...),并且我希望我的步骤代码能够优雅地处理此问题,因此我在步骤中进一步采用了以下逻辑:
if ($alert_wmi_state -eq ('$' + '(ESCAPE_SQUOTE(WMI(State)))')) {
...
}
Run Code Online (Sandbox Code Playgroud)
...理论是,$从 中分离(ESCAPE_SQUOTE...将合理地意味着这不被识别为令牌,因此不会被替换,因此测试将按字面意思读取:
if ($alert_wmi_state -eq '$(ESCAPE_SQUOTE(WMI(State)))') {
...
}
Run Code Online (Sandbox Code Playgroud)
但是,手动运行作业时,在运行我的任何代码之前,SQL 代理总是会在该步骤中出错(无论它是配置为CmdExec作业步骤类型还是PowerShell作业步骤类型),并显示错误Variable WMI(State) not found。
我的猜测是,这是因为替换ESCAPE_SQUOTE发生在步骤代码实际解析/加载之前,因此代理永远不会运行该步骤。
我希望我可以有两个步骤,一个带有令牌,一个没有,并且让标记化步骤的失败操作启动非标记化步骤,但是步骤代码的重复是不可取的。
所以,我的问题是,有什么方法可以优雅地处理步骤代码中不存在步骤令牌的情况吗?
我正在尝试从一堆服务器获取磁盘空间报告并将它们插入到 sql 表中..
下面是我正在尝试做的示例,服务器名称将从表中填充并作为逗号分隔列表传递。即使传递一台服务器也有相同的结果
set @ps = 'powershell.exe -noexit -c "
$computers=Get-WmiObject -Class Win32_Volume '+@servernames+'
foreach($computer in $computers)
{
$pscomputername=$computer.pscomputername
$name=$computer.name
$capacity=$computer.capacity
$freespace=$computer.freespace
$Label=$computer.Label
$insertquery="
INSERT INTO [dbo].[temp_disksdata]
(
[servername] ,
[DiskName] ,
[Capacity(GB)] ,
[FreeSpace(GB)],
[label]
)
VALUES
(''$pscomputername'' ,
''$name'' ,
''$capacity'',
''$freespace'',
''$Label''
)
GO
"
Invoke-SQLcmd -query $insertquery -ServerInstance ''someserver'' -Database dbname
}
"';
Run Code Online (Sandbox Code Playgroud)
现在我尝试将变量传递给 xp_cmdshell,如下所示
execute xp_cmdshell @ps;
Run Code Online (Sandbox Code Playgroud)
当在 SSMS 中调用时,上面返回 null,但在 powershell 中工作..
任何想法为什么?
以下是我尝试过的一些事情
1. shell 和 ssms 都使用相同的帐户(admin) 2.
尝试了多种方法,例如导入模块
3.XP_CMDshell 有效,但这仅针对此查询返回 …
我正在通过 PowerShell 的专用管理员连接 (DAC) 连接到 SQL Server(2016 和 2017 最新版本)。
SQL Server 错误日志中记录以下错误消息:
日期 2019 年 4 月 2 日下午 1:59:13 记录 SQL Server(当前 - 2019 年 4 月 2 日下午 1:59:00)
源登录
消息
无法连接,因为已存在最大数量“1”的专用管理员连接。在建立新连接之前,必须通过注销或结束进程来删除现有的专用管理员连接。[客户端:127.0.0.1]
查询成功运行。已经尝试了许多连接字符串管理迭代;这是迄今为止最强大的。
Stack Exchange 上有一个解决方案,该解决方案涉及在关闭连接之前终止 spid,但这也会向 SQL Server 错误日志中抛出一条令人讨厌的消息,因此没有什么乐趣。
检查sys.dm_exec_sessions没有发现任何有趣的事情;使用此技术,没有连接保持打开状态。下面的 PowerShell 有一个虚拟查询,我无法谈论为什么我们要以这种方式连接,因为它是专有的,但它是 100% 必要的,它是一个非常快速的连接,我需要每 10 次执行一次分钟。
这个错误只是噪音。DAC 查询按预期运行和工作。
即使在静止的系统上重新启动,每次都会记录该错误。没有其他 DAC 连接正在使用 - 如果有,Powershell 会在命令提示符处抛出明显的错误消息。
有趣的是,当使用 时sqlcmd,SQL Server 错误日志中不会记录任何错误消息。
#begin powershell script
$SqlServerName = "server\instance"
$DbQuery = "
INSERT INTO master.dbo.sometable(value1,value2) …Run Code Online (Sandbox Code Playgroud) 如何本地记录来自 PowerShell Invoke-Sqlcmd 的输出?
我正在使用 Invoke-Sqlcmd 循环遍历一个大的(50,000-90,000 个 SQL 文件,每个文件中有 1-10 个插入)小 SQL 插入语句集。大多数插入语句运行正确,但一些字符串太长,我收到“字符串或二进制数据将被截断”错误。
现在我正在使用 Start-Transcript 来捕获输出并识别有问题的插入语句,但 Start-Transcript 捕获了所有内容。我只想捕获错误 - 或者 - 只捕获 Invoke_Sqlcmd 语句输出。
如果这行得通(我认为应该如此),我就准备好了:
Invoke-Sqlcmd -InputFile $sql -ServerInstance LocalHost -Database Test_DB -Credential $pwd -Verbose -OutputSqlErrors $true | Out-File -FilePath "C:\Temp\Errorlog.txt" -Append
Run Code Online (Sandbox Code Playgroud)
或者,如果这有效:
Invoke-Sqlcmd -InputFile $sql -ServerInstance LocalHost -Database Test_DB -Credential $pwd -Verbose -OutputSqlErrors $true | Tee-Object -FilePath "C:\Temp\Errorlog.txt" -Append
Run Code Online (Sandbox Code Playgroud)
但这些都不起作用。
我也尝试过这种怪物,但我根本没有从中得到任何错误:
$sqls = (Get-ChildItem -Path "I:\2019_06_24\_SQL"-Filter *.sql | Sort-Object -Property CreationTime).FullName
foreach ($sql in $sqls)
{
$Error.Clear()
try …Run Code Online (Sandbox Code Playgroud)