嵌套循环中的语法不正确

时间:2019-05-16 07:32:53

标签: powershell

我有一个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

有人可以告诉我不正确的语法来自何处吗?我已经看了好几个小时了,无法找出答案?

2 个答案:

答案 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

    }

像锤子一样工作!!!!!!!!!!!!