Invoke-Sqlcmd运行脚本两次

时间:2015-10-22 00:21:33

标签: sql-server powershell

我遇到了一个非常奇怪的问题,可以重复。

基本上,我使用invoke-sqlcmd通过使用-inputfile来调用脚本文件,但是如果脚本文件有一些执行错误(比如插入一个列不应为null的表),脚本文件将被执行两次。我也可以看到来自探查器的两次执行。

以下是重现问题的方法(我的环境:Win 8.1 + SQL2014 + PS 5.0)

  1. 在数据库中创建两个表

    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. 现在使用以下两行创建一个sql文件(让我们调用它,c:\ temp \ t.sql)

    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. 运行以下PS cmdlet

    invoke-sqlcmd -Server "<my_local_server>" -database TestDB -inputfile "c:\temp\t.sql"
    
  4. 如果您打开SSMS查询窗口并执行以下操作,您的PS将返回错误

    select * from TestDB.dbo.s
    

    你会看到两条记录而不是一条记录。 Two records 另一方面,如果我运行sqlcmd.exe,则没有这样的问题,即dbo中的一条记录。 我错过了SQLPS中的一些配置吗?

4 个答案:

答案 0 :(得分:2)

我看到你在MSDN数据库引擎论坛上问了同样的问题: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。以下是该主题的SMO解决方法。

$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);

答案 1 :(得分:1)

即使我有类似的问题。

通过向Invoke-Sqlcmd cmdlet添加-QueryTimeout参数来修复它。

基本上,似乎查询以某种方式超时,并且由于Invoke-Sqlcmd cmdlet中的错误,它会尝试再次插入它。奇怪,但试试这个。保持查询超时足够大,以便执行查询。

答案 2 :(得分:1)

使用Microsoft的修复程序更新此步骤:

SQL Server 2016 SP1的累积更新2
SQL Server 2014 Service Pack 2的累积更新4

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

答案 3 :(得分:0)

我知道这是一个老线程,但也许它可以帮助某人。

我发现你是否移动你的线路&#34;选择1,&#39;早上好&#39;&#34;在你的例子中,在insert语句之前有异常,它就像预期的那样工作。

我在try catch中遇到了类似的问题,当第一个返回值被异常时会被忽略,所以我必须确保第一行是Select 1.奇怪的bug。