Reputation: 1922
I am trying to automate the process of importing GNAF (location dataset for Australia) into a new database. The problem I am having is that when I try to the database and recreate it I get an error saying the database is in use:
Invoke-Sqlcmd : Cannot drop database "GNAF" because it is currently in use. At line:11 char:5
+ Invoke-Sqlcmd -Query "IF EXISTS (SELECT name FROM master.dbo.sysd ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Invoke-Sqlcmd], SqlPowerShellSqlExecutionException
+ FullyQualifiedErrorId : SqlError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand Invoke-Sqlcmd : Database 'GNAF' already exists. Choose a different database name. At line:15 char:5
+ Invoke-Sqlcmd -Query "CREATE DATABASE GNAF" -serverinstance $Serv ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Invoke-Sqlcmd], SqlPowerShellSqlExecutionException
+ FullyQualifiedErrorId : SqlError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
In the activity monitor for SSMS it shows:
This is the function that is being called:
function importQNAF {
$ScriptPath = "C:\Users\owain.esau\Scripts\PowerShell\SQL-Server\TRIS Database Anon\" # change to pwd for live
$QNAFpath1 = ( $ScriptPath + "GNAF\G-NAF\G-NAF AUGUST 2017\Standard\" )
$QNAFpath2 = ( $ScriptPath + "GNAF\G-NAF\G-NAF AUGUST 2017\Authority Code\" )
$GNAF_ImportData_Path = ( $ScriptPath + "\SQLScripts\GNAF_ImportData.sql" )
(Get-Content $GNAF_ImportData_Path).replace("Powershell To Change#1", $QNAFpath1) | Set-Content $GNAF_ImportData_Path
(Get-Content $GNAF_ImportData_Path).replace("Powershell To Change#2", $QNAFpath2) | Set-Content $GNAF_ImportData_Path
## Drop and Create Table
Invoke-Sqlcmd -Query "IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name ='GNAF')
BEGIN
ALTER DATABASE GNAF SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE GNAF;
END
;" -serverinstance $ServerAddress;
Start-Sleep -s 5;
Invoke-Sqlcmd -Query "CREATE DATABASE GNAF" -serverinstance $ServerAddress;
Start-Sleep -s 5;
Invoke-Sqlcmd -InputFile ( $ScriptPath + "SQLScripts\GNAF_CreateTables.sql" ) -serverinstance $ServerAddress;
try {
Invoke-Sqlcmd -InputFile ( $ScriptPath + "SQLScripts\GNAF_ImportData.sql" ) -serverinstance $ServerAddress -querytimeout 0;
} catch {
if ($error -match "Access is denied.") {
Write-Host "[!] ERROR: Access denied to GNAF folder."
Write-Host "----------------------------------------"
Write-Host "You have two options: "
Write-Host ""
Write-Host " 1) Give MSSQLSERVER full access to" $ScriptPath
Write-Host " 2) Copy the1 folder: " $ScriptPath"GNAF to the MSSQL Source folder (C:\Program Files\SQL Server)"
Do {
switch(Read-Host "Please choose an action (1 or 2)") {
1 {
$Acl = (Get-Item $ScriptPath).GetAccessControl('Access');
$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule("NT SERVICE\MSSQLSERVER", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow");
$Acl.SetAccessRule($Ar);
Set-Acl $ScriptPath $Acl;
importQNAF;
}
2 { Write-Host "Not coded yet"; }
default { "Invalid Entry, must be 1 or 2"; }
}
} Until ($choice -eq 1 -or $choice -eq 2)
}
}
(Get-Content $GNAF_ImportData_Path).replace($QNAFpath1, "Powershell To Change#1") | Set-Content $GNAF_ImportData_Path (Get-Content $GNAF_ImportData_Path).replace($QNAFpath2, "Powershell To Change#2") | Set-Content $GNAF_ImportData_Path } The script I am using to actually import the data into SQL server is almost identical to the one found on this page:
It works fine directly in SSMS. Also, I don't think my error match is picking up the correct error, instead it is matching to all errors.
--- Update ----------------------------------------------
Managed to get it to run when i restart the MSSQLSERVER service at the start of the function.
The problem now is that it times out:
Invoke-Sqlcmd : Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
BULK INSERT [MB_2011] FROM 'C:\Users\owain.esau\OneDrive\Scripts\PowerShell\SQL-Server\TRIS Database Anon\GNAF\G-NAF\G-NAF AUGUST 2017\Standard\ACT_MB_2011_psv.psv' WITH ( FIELDTERMINATOR = '|', ROWTERMINATOR =
'\n', FIRSTROW = 2, ROWS_PER_BATCH=100000, TABLOCK)
At line:30 char:9
+ Invoke-Sqlcmd -InputFile ( $ScriptPath + "SQLScripts\GNAF_Imp ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Invoke-Sqlcmd], SqlPowerShellSqlExecutionException
+ FullyQualifiedErrorId : SqlError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
It only runs for around 45 seconds before this error pops up, the actual script being run takes around 3 - 5 minutes run in SSMA.
(The function has been updated a bit)
Upvotes: 1
Views: 719
Reputation: 17171
You need to terminate any existing, open connections to the database.
Here's the easiest method (it basically forces all other connections to be killed)
IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name ='GNAF')
BEGIN
ALTER DATABASE GNAF SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE GNAF;
END
;
Upvotes: 2