我正在尝试通过将PowerShell与SMO一起使用来生成数据库脚本。我将全部生成到一个.sql文件中。除了USE DATABASE语句,我似乎能够获得所有内容。 CREATE DATABASE部分在其上面具有USE MASTER。脚本化的其他对象(例如表和存储的proc)在其上方没有脚本化的USE DATABASE,因此可以在MASTER数据库中创建它们。
我尝试遍历所有脚本选项,但似乎没有一个在CREATE TABLE语句之前添加USE DATABASE语句。我已经尝试了各种脚本选项组合,但是没有任何东西可以提供所需的输出。
我正在寻找原因,为什么它不生成USE DATABASE语句。 在此先感谢您的任何帮助。
这是我正在使用的整个PowerShell脚本。我最初是从Internet上的某个地方获得的,并对它进行了修改。甚至原始脚本也没有在表脚本之前输出USE DATABASE语句。
function Invoke-ScriptSqlDatabase {
[CmdletBinding()]
param(
#SqlInstance - Source SQL Server instance.
[Parameter(Mandatory = $true)]
[string]$SqlInstance,
#Database, or array of databases, to script.
[Parameter(Mandatory = $true)]
[array]$Database,
#SqlAuthentication - Boolean. Default is false (use Windows Authentication)
[Parameter(Mandatory = $false)]
[boolean]$SqlAuthentication,
#Directory - This is where the script will reside.
[Parameter(Mandatory = $true)]
[string]$Directory,
#ContinueScriptingOnError - If an error is encountered while generating the script, continue if $true.
[Parameter(Mandatory = $false)]
[boolean]$ContinueScriptingOnError
)
BEGIN {
#import the SQLServer module
if (-not(get-module -name SqlServer)) {
if (Get-Module -ListAvailable | Where-Object { $_.Name -eq "SqlServer" }) {
import-module "SqlServer"
}
else {
throw "This function requires the SqlServer module.
}
}
#append a timestamp to the generated script files
$DateTimestamp = $(get-date -f "yyyyMMdd-HHmmss")
#create the output directory if not exists
if (-not( Test-Path "$Directory\" -PathType Container)) {
New-Item -ItemType Directory -Path $Directory
}
#setup connection to the Sql instance.
$SqlSMO = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server -ArgumentList $SqlInstance
#if SqlAuthentication is true, grab user credentials
if ($SqlAuthentication) {
$cred = Get-Credential
$SqlSMO.ConnectionContext.LoginSecure = $false
$SqlSMO.ConnectionContext.set_Login($cred.UserName)
$SqlSMO.ConnectionContext.set_SecurePassword($cred.Password)
}
else {
$SqlSMO.ConnectionContext.LoginSecure = $true
}
#try connecting
try { $SqlSMO.ConnectionContext.Connect() }
catch {
throw "Can't connect to $SqlInstance."
}
}
PROCESS {
#trap errors
Trap {
# Handle the error
$err = $_.Exception
write-warning $err.Message
while ( $err.InnerException ) {
$err = $err.InnerException
write-warning $err.Message
};
# Stop the script.
break
}
#loop over the array of databases and generate scripts
$Database | ForEach-Object {
#Check OS. If Linux or Windows. Update directory.
if($env:OS) {
$Filename = "$($Directory)\$($_)_$($DateTimestamp).sql"
}
else {
$Filename = "$($Directory)/$($_)_$($DateTimeStamp).sql"
}
$db = $SqlSMO.Databases[$_]
if (-not($db)) {
throw "The $_ database was not found on $SqlInstance."
}
#Create database script options
$databaseSCRP = New-Object Microsoft.SqlServer.Management.Smo.Scripter($SqlSmo)
$databaseSCRP.Options.ScriptBatchTerminator = $true
$databaseSCRP.Options.IncludeHeaders = $true
$databaseSCRP.Options.ExtendedProperties = $true
$databaseSCRP.Options.ToFileOnly = $true
$databaseSCRP.Options.Filename = $Filename
$databaseSCRP.Options.SchemaQualify = $true
$databaseSCRP.Options.ScriptSchema = $true
$databaseSCRP.Options.IncludeDatabaseContext = $true
$databaseSCRP.Options.NoFileGroup = $true
$databaseSCRP.Options.NoFileStream = $true
$databaseSCRP.Options.Permissions = $true
$databaseSCRP.Options.ScriptForCreateDrop = $true
$databaseSCRP.Options.IncludeIfNotExists = $true
$databaseSCRP.Options.DriAll = $true
$databaseSCRP.Options.ScriptDrops = $true
$databaseSCRP.Options.WithDependencies = $true
$databaseSCRP.Options.EnforceScriptingOptions = $true
$databaseSCRP.Options.Encoding = [System.Text.Encoding]::UTF8
$databaseSCRP.Script($db)
#Script database objects
$transfer = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Transfer -ArgumentList $db
$ScriptOptions = New-Object -TypeName Microsoft.SqlServer.Management.Smo.ScriptingOptions
#setup options
$ScriptOptions.ExtendedProperties = $true
$ScriptOptions.DriAll = $true
$ScriptOptions.Indexes = $true
$ScriptOptions.Triggers = $true
$ScriptOptions.ScriptBatchTerminator = $true
$ScriptOptions.IncludeHeaders = $true
$ScriptOptions.IncludeDatabaseContext = $true
$ScriptOptions.Permissions = $true
$ScriptOptions.Statistics = $true
$ScriptOptions.ScriptSchema = $true
$ScriptOptions.SchemaQualify = $true
$ScriptOptions.ToFileOnly = $true
$ScriptOptions.IncludeIfNotExists = $true
$ScriptOptions.FileName = $FileName
$ScriptOptions.AppendToFile = $true
$ScriptOptions.Encoding = [System.Text.Encoding]::UTF8
#Continue scripting if an error is encountered? Errors can be seen if objects have dependencies on other objects that are no longer in place.
if ($ContinueScriptingOnError) {
$ScriptOptions.ContinueScriptingOnError = $true
}
$transfer.Options = $ScriptOptions
$transfer.ScriptTransfer()
}
}
END {
write-host "Script complete. All scripts are located in the $Directory folder." -ForegroundColor Green
}
}}
它生成的输出是:
USE [master]
GO
/****** Object: Database [Testing_4] Script Date: 6/11/2019 12:34:11 PM ******/
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'Testing_4')
BEGIN
CREATE DATABASE [Testing_4]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'Testing_4', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQL\DATA\Testing_4.mdf' , SIZE = 8192KB , MAXSIZE = UNLIMITED, FILEGROWTH = 65536KB )
LOG ON
( NAME = N'Testing_4_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.SQLEXPRESS\MSSQL\DATA\Testing_4_log.ldf' , SIZE = 8192KB , MAXSIZE = 2048GB , FILEGROWTH = 65536KB )
COLLATE SQL_Latin1_General_CP1_CI_AS
END
GO
... removed some output to save space. I believe there should be a USE [DATABASE] statement here so that the objects to follow are generated in the correct database...
ALTER DATABASE [Testing_4] SET READ_WRITE
GO
/****** Object: Table [dbo].[MorePeople] Script Date: 6/11/2019 12:34:16 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[MorePeople]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[MorePeople](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Firstname] [nchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Lastname] [nchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Username] [nchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[IsActive] [bit] NULL,
CONSTRAINT [PK_MorePeople] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
我用于在PowerShell中执行此功能的命令行为:
Invoke-ScriptSqlDatabase -SqlInstance localhost\sqlexpress -Database Testing_4 -SqlAuthentication $false -Directory "C:\SQLServer\CreateScriptOuts" -FileUniqueId "abc137"
我正在寻找原因,为什么它不生成USE DATABASE语句以及如何解决它。
在此先感谢您的帮助。