我有一个Power-shell脚本来删除最近30天内没有连接的数据库。我已将脚本编码如下:
$SQLInstances = "sql2016", "sql2014", "sql2012"
$SQLQuery = "exec usp_ConnectionsCount"
foreach ($sqLInstance in $SQLInstances) {
Invoke-Sqlcmd -ServerInstance $sqLInstance -Database "master" -Query $SQLQuery
}
Write-Output "Any database that has not been used in the last 30 days will be dropped"
Write-Output "Here is a list of SQL Instances being monitored:" $SQLInstances
$DBQuery = "SELECT Name as DatabaseName FROM [SQLConnections] WHERE number_of_connections = 0 AND DATEDIFF(day, timestamp, GetDate()) > 30"
$DropDb = "IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = '$UnusedDB') DROP DATABASE $UnusedDB"
foreach ($sqLInstance in $SQLInstances) {
$Databases = Invoke-Sqlcmd -ServerInstance $sqLInstance -Database "master" -Query $DBQuery
Write-Output "List of Databases to be dropped"
$Databases
foreach ($UnusedDB in $Databases) {
Invoke-Sqlcmd -ServerInstance $sqLInstance -Database "master" -Query $DropDb
}
}
我的代码对我来说很酷,但是当我运行它时,它说
Invoke-Sqlcmd:“数据库”附近的语法不正确。
我不知道问题出在哪里。另外,用于创建SQLConnections表的代码为:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[SQLConnections](
[server] [nvarchar](130) NOT NULL,
[name] [nvarchar](130) NOT NULL,
[number_of_connections] [int] NOT NULL,
[timestamp] [datetime] NOT NULL
) ON [PRIMARY]
GO
usp_ConnectionsCount
的代码如下:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE usp_ConnectionsCount
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [SQLConnections]
SELECT @@ServerName AS server
,NAME AS dbname
,COUNT(STATUS) AS number_of_connections
,GETDATE() AS timestamp
FROM sys.databases sd
LEFT JOIN master.dbo.sysprocesses sp ON sd.database_id = sp.dbid
WHERE database_id NOT BETWEEN 1
AND 4
GROUP BY NAME
END
有人可以告诉我不正确的语法来自何处吗?我已经看了好几个小时了,无法找出答案?
答案 0 :(得分:1)
您在:中有一个字符串引用问题。
$DropDb = "IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = '$UnusedDB') DROP DATABASE $UnusedDB"
Powershell不会替换单个引号中的变量,而Powershell不会替换$UnusedDB
并将其保留为字符串中的文本。
您可以将其更改为:
$DropDb = "IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = `"$UnusedDB`") DROP DATABASE $UnusedDB"
您可以找到有关报价规则here的更多信息。
您也可以尝试通过-f
运算符格式化字符串,文档为here。
希望有帮助。
答案 1 :(得分:0)
因此,我放弃了让Powershell进行大部分工作的想法。我设法使用SQL代码完成了大部分工作:
$ SQLInstances =“ sql2016”,“ sql2014”,“ sql2012”
Write-Output "Any database that has not been used in the last 30 days will be dropped"
Write-Output "Here is a list of SQL Instances being monitored:" $SQLInstances
$DropDb = " --Exec stored procedure to gather information regarding DB connections
EXEC usp_fpmConnectionsCount
IF OBJECT_ID('tempdb..#TempSQLConnections1') IS NOT NULL DROP TABLE #TempSQLConnections
SELECT Distinct(fund.name)
INTO #TempSQLConnections
FROM FundSQLConnections AS fund
INNER JOIN
sys.databases as sdb
on fund.name = sdb.name
WHERE number_of_connections = 0 AND DATEDIFF(day, timestamp, GetDate()) > 30
GO
DECLARE @dbnames nvarchar(max)
DECLARE @statement nvarchar(max)
SET @dbnames = ''
SET @statement = ''
SELECT @dbnames = @dbnames + ',[' + name + ']' from #TempSQLConnections
IF len(@dbnames) = 0
begin
print 'no databases to drop'
end
ELSE
begin
set @statement = 'drop database ' + substring(@dbnames, 2, len(@dbnames))
print @statement
exec sp_executesql @statement
print @dbnames + 'Has been dropped'
end
DROP TABLE #TempSQLConnections "
foreach($sqLInstance in $SQLInstances) {
Invoke-Sqlcmd -ServerInstance $sqLInstance -Database "master" -Query $DropDb
}
像锤子一样工作!!!!!!!!!!!!