【问题标题】:Powershell Invoke-Sqlcmd doesn't capture all verbose outputPowershell Invoke-Sqlcmd 不捕获所有详细输出
【发布时间】:2019-06-21 14:54:22
【问题描述】:

我创建了以下 powershell (v2) 脚本来对目标数据库执行查询并构建另一个要运行的查询/查询:

$sql = @"
DECLARE @Tables CURSOR;
DECLARE @TableName NVARCHAR(200);

BEGIN
    SET @Tables = CURSOR FOR
    SELECT TABLE_NAME
    FROM test.INFORMATION_SCHEMA.TABLES 
    WHERE TABLE_TYPE='BASE TABLE' 
    AND TABLE_NAME LIKE 'x%'

    OPEN @Tables 
    FETCH NEXT FROM @Tables 
    INTO @TableName
    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT 'SELECT TOP 1 * FROM test.dbo.' + @TableName
        FETCH NEXT FROM @Tables 
        INTO @TableName 
    END; 

    CLOSE @Tables ;
    DEALLOCATE @Tables;
END;
"@
$ps = [PowerShell]::Create()
$ps.AddCommand("Invoke-Sqlcmd").AddParameter("Query", $sql).AddParameter("Verbose")
$ps.Invoke()

$sqlOutput = $ps.Streams.Verbose
$sqlOutputToRun = $nul
$sqlOutput | foreach {
    $sqlOutputToRun += ($_.ToString() + "`n")
}
$sqlOutputToRun = @"
$sqlOutputToRun
"@

$sqlOutputToRun

在脚本结束时,我打印了必须执行的查询,但不幸的是变量 $sqlOutputToRun 仅包含大约 3/4 的预期输出。 我想由于尺寸的原因,输出会以某种方式被削减,但我不确定如何扩展它。

你知道缺少什么吗?

【问题讨论】:

  • 为什么要使用CURSOR 来执行此操作?为什么不使用STUFFFOR XML PATH 方法一键完成此操作?
  • 我只粘贴了部分脚本。脚本包含更多的操作,游标对我来说处理起来更灵活,但它是描述这个问题的冗余信息。
  • 为什么要在新环境中调用 PowerShell,而不是直接调用 Invoke-Sqlcmd(或 sqlcmd.exe,如果需要纯文本输出)并通过管道输出?
  • 因为我无法得到查询的输出。输出包含由 PRINT 命令生成的文本,而不仅仅是来自数据库的结果。这是我找到的唯一解决方案 (stackoverflow.com/questions/4511498/…)
  • 好的,那么我明显的下一个问题是为什么您使用PRINT 而不是SELECT 将输出捕获为正确的结果集,这实际上是Invoke-Sqlcmd 的设计目的一起工作。 PRINT 有自己的字符串被切断的问题。 (话虽如此,Invoke-Sqlcmd 可能无法正确处理多个结果集——根据 Larnu,如果您不能将所有结果都放入一个查询中,请考虑在表变量中插入中间结果,然后在所有内容的末尾选择它,这仍然比捕获PRINT 语句更容易。)

标签: sql-server powershell powershell-2.0 invoke-sqlcmd


【解决方案1】:

如果你不能离开你的光标,为什么你不能做这样的事情?

$sql = "
DECLARE @Tables CURSOR;
DECLARE @TableName NVARCHAR(200);
DECLARE @Results TABLE (ResultQuery NVARCHAR(MAX)) 

BEGIN
    SET @Tables = CURSOR FOR
    SELECT TABLE_NAME
    FROM testdb.INFORMATION_SCHEMA.TABLES 
    WHERE TABLE_TYPE='BASE TABLE' 
    --AND TABLE_NAME LIKE 'x%'

    OPEN @Tables 
    FETCH NEXT FROM @Tables 
    INTO @TableName
    WHILE @@FETCH_STATUS = 0
    BEGIN
        INSERT INTO @Results (ResultQuery)
        SELECT 'SELECT TOP 1 * FROM test.dbo.' + @TableName

        -- PRINT 'SELECT TOP 1 * FROM test.dbo.' + @TableName
        FETCH NEXT FROM @Tables 
        INTO @TableName 
    END; 

    CLOSE @Tables ;
    DEALLOCATE @Tables;
END;
SELECT * FROM @Results;"
$sqlOutputToRun = Invoke-Sqlcmd -query $sql
$sqlOutputToRun

【讨论】:

    【解决方案2】:

    一旦您转储 print 语句以支持结果集,您也可以转储游标,只需运行一个简单的查询,例如:

        select 'SELECT TOP (1) * FROM '+ quotename(table_catalog) + '.' + quotename(table_schema) + '.' + quotename(table_name)
        FROM INFORMATION_SCHEMA.TABLES 
        WHERE TABLE_TYPE='BASE TABLE' 
        AND TABLE_NAME LIKE 'x%'
    

    所以在 Powershell 中:

    $sql = @"
            select 'SELECT TOP (1) * FROM '+ quotename(table_catalog) + '.' + quotename(table_schema) + '.' + quotename(table_name)
            FROM INFORMATION_SCHEMA.TABLES 
            WHERE TABLE_TYPE='BASE TABLE' 
           -- AND TABLE_NAME LIKE 'x%'
    "@
    
    $sqlOutputToRun = $nul
    
    invoke-sqlcmd $sql | foreach { 
         $sqlOutputToRun += $_[0] + "`n"
    }
    
    $sqlOutputToRun
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-31
      • 2021-12-17
      • 1970-01-01
      • 1970-01-01
      • 2011-06-13
      • 1970-01-01
      • 2017-05-27
      • 1970-01-01
      相关资源
      最近更新 更多