Reputation: 1180
I have a power-shell script to drop databases that have no connections in the last 30 days. I have coded the script as below:
$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
}
}
My code looks cool to me but when I run it, it says
Invoke-Sqlcmd : Incorrect syntax near 'DATABASE'.
I can't figure out where the problem is. Additionally the code for creating SQLConnections table is:
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
And the code for the usp_ConnectionsCount
is as follows:
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
Can someone tell me where the incorrect syntax is coming from? I have been looking at this for hours and cant figure out?
Upvotes: 0
Views: 92
Reputation: 1180
So, I have abandoned the idea of letting powershell do most of the work. I have managed to use SQL code to do most of the work:
$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
}
Works like a Hammer!!!!!!!!!!!!
Upvotes: 0
Reputation: 11254
You've a string quoting problem in :
$DropDb = "IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = '$UnusedDB') DROP DATABASE $UnusedDB"
Powershell won't replace variables in a single quoted string, there Powershell won't replace $UnusedDB
and keeps it as text in the string.
You can change it to:
$DropDb = "IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = `"$UnusedDB`") DROP DATABASE $UnusedDB"
You can find more about quoting rules here.
You can also try formatting the string via the -f
operator, documentation is here.
Hope that helps.
Upvotes: 1