Неверный синтаксис во вложенном цикле - PullRequest
0 голосов
/ 16 мая 2019

У меня есть сценарий 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: неверный синтаксис рядом с DATABASE.

Я не могу понять, где проблема.Кроме того, код для создания таблицы 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 ]

1 голос
/ 16 мая 2019

Вы столкнулись с проблемой цитирования строк в:

$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"

Подробнее о правилах цитирования здесь .

Вы также можете попробовать отформатировать строку с помощью оператора -f, документация здесь .

Надеюсь, это поможет.

0 голосов
/ 16 мая 2019

Итак, я отказался от идеи позволить 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

    }

Работает как молоток !!!!!!!!!!!!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...