Sql-Server

如何使用帶變數的 Invoke-SqlCmd 僅輸出 SQL 命令或其他類似方法?

  • June 1, 2018

我有一個*.sql執行的大文件Invoke-Sqlcmd和用於執行某些任務的變數,當我遇到問題時,由於變數而調試很痛苦,我想記錄即將執行的 SQL 腳本。

是否有一種合理的本地方式來生成最終SQL將通過變數替換執行而不實際執行?

這是我執行以將 *.bak 恢復到各種環境的範例:

Invoke-Sqlcmd -InputFile $sqlFile -QueryTimeout 0 -ServerInstance 'SQLServer' -Database 'Master' -Variable @("DatabaseBAK=$TransactDB", "Database=$TargetDatabase") -Verbose

SQL 文件:

USE [master]

print 'Killing connections to database $(Database)'
DECLARE @kill varchar(8000) = '';

SELECT @kill = @kill + 'kill ' + CONVERT(varchar(5), session_id) + ';'
FROM sys.dm_exec_sessions
WHERE database_id  = db_id('$(Database)') 
and session_id <> @@SPID
EXEC(@kill);
GO
USE [master]

print '[Info] RESTORE DATABASE [$(Database)]'
print '[Info] FROM DISK = N''$(DatabaseBAK)'''
print 'Starting restore-------------------->'
RESTORE DATABASE [$(Database)]
FROM DISK = N'$(DatabaseBAK)'
WITH FILE = 1
   ,NOUNLOAD
   ,REPLACE
   ,STATS = 5
GO
print '<--------------------End restore'

我想以某種方式以 Invoke-SqlCmd 的方式輸出上面的變數替換。

我想出了一個聰明的方法set quoted_identifier off

在此處輸入圖像描述

電源外殼

$sqlFile = "C:\Users\user\Desktop\TestOutput.sql"
$begin = 'set quoted_identifier off print "'
$end = '" set quoted_identifier on'

Invoke-Sqlcmd -InputFile $sqlFile -QueryTimeout 0 -ServerInstance 'Server' -Database 'Database' -Variable @("begin=$begin", "end=$end") -Verbose

$begin = '--Begin'
$end = '--End'

Invoke-Sqlcmd -InputFile $sqlFile -QueryTimeout 0 -ServerInstance 'Server' -Database 'Database' -Variable @("begin=$begin", "end=$end") -Verbose

TSQL

/*
$(begin) is either
   set quoted_identifier off print "
   or
   --Begin
*/

$(begin)
select SALESID from SALESTABLE where SALESID = 'SO-000003'
select SALESID from SALESTABLE where SALESID = 'SO-000004'
$(end)

/*
$(end) is either
   " set quoted_identifier on
   or
   --End
*/

無需重新發​​明輪子,只需使用dbatools - restore-dbadatabase

廣泛涵蓋了您可能需要的所有場景

注意:dbatools 也有更好的 invoke-sqlcmd –> invoke-sqlcmd2版本,-ParseGO可以使用批處理分隔符來解析腳本,GO並且是更優化的版本。

引用自:https://dba.stackexchange.com/questions/208517