6

I experienced a very strange issue and can be repeated.

Basically, I use invoke-sqlcmd to call a script file by using -inputfile, but if the script file has some execution error (like insert into a table where a column should not be null), the script file will be executed twice. I can see the two executions from profiler as well.

Here is the way to reproduce the issue (My environment: Win 8.1 + SQL2014 + PS 5.0)

  1. create two tables in a database

    Use TestDB
    
    create table dbo.s (id int identity primary key, b varchar(50));
    
    create table dbo.t (id int primary key, s_id int, b varchar(50));
    alter table dbo.t add constraint fk_t foreign key (s_id) references dbo.s(id)
    
  2. Now create a sql file (let's call it, c:\temp\t.sql) with the following two lines

    insert into dbo.s ( b) select  'hello world'
    insert into dbo.t (s_id, b) -- purposely missing id to cause an error
    select 1, 'good morning'
    
  3. Run the following PS cmdlet

    invoke-sqlcmd -Server "<my_local_server>" -database TestDB -inputfile "c:\temp\t.sql"
    

Your PS will return an error, now if you open an SSMS query window and do the following

select * from TestDB.dbo.s

You will see two records there instead of one. Two records On the other hand, if I run sqlcmd.exe, there is NO such issue, i.e. just one record in dbo.s. Is there some configuration in SQLPS I missed?

1
  • Reproducible. Maybe the dba.stackexchange.com folks have more insight, so I'll vote for migrate. Commented Oct 22, 2015 at 11:09

4 Answers 4

2

I see you asked this same question on the MSDN Database Engine forum: https://social.msdn.microsoft.com/Forums/en-US/d4167226-2da7-49ec-a5c2-60e964785c2c/powershell-invokesqlcmd-calls-stored-procedure-second-time-after-query-timeout-is-expired. Below is the SMO workaround from that thread.

$SqlServerName = "YourServer";
$DatabaseName = "YourDatabase";
$ScriptFileName = "C:\Scripts\YourSqlScriptFile.sql";

Add-Type -Path "C:\Program Files\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.Smo.dll";

$sr = New-Object System.IO.StreamReader($ScriptFileName);
$script = $sr.ReadToEnd();
$sr.Close();

$Server = New-Object Microsoft.SqlServer.Management.Smo.Server($SqlServerName);
$db = $Server.Databases[$DatabaseName];
$db.ExecuteNonQuery($script);
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks @Dan. I know an alternative way to solve this issue, because when I use invoke-sqlcmd2 (a function in sqlpsx link, which uses System.Data.SqlClient.SqlCommand, there is no problem. I guess my question or concern should be "this is a BIG bug for SQLPS module"
Worked for me without the "Add-Type" line.
I didn't need the "Add-Type" line, when executing from the console directly. Didn't work without it in a script though. This path didn't exist in my environment, so I used [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null instead.
@jumxozizi, Add-Type or LoadWithPartialName isn't needed if the assembly is already loaded into the current app domain. I's needed if you run it from a stand-alone PowerShell ISE or command-line.
2

Updating this tread with the fix from Microsoft:

Cumulative Update 2 for SQL Server 2016 SP1
Cumulative Update 4 for SQL Server 2014 Service Pack 2

FIX: "Invoke-sqlcmd" cmdlet executes a query statement multiple times if an error occurs in SQL Server 2014 or 2016

1 Comment

Great. It really helped to me solve a long pending issue.
1

Even i had a similar issue.

Fixed it by adding -QueryTimeout parameter to Invoke-Sqlcmd cmdlet.

Basically it seems that the query somehow times out and due to a bug in Invoke-Sqlcmd cmdlet it tries to insert it again. Strange but try this. Keep the query timeout big enough for the query to execute.

Comments

0

I know this is a old thread, but maybe it can help someone.

I found out if you move your line "select 1, 'good morning'" in your example before the insert statement, which has the exception, it works like intended.

I had a similar Issue with try catch, that the first return value will be ignored when it's an exception, so I had to make sure that the first line was Select 1. Strange bug.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.