【问题标题】:Invoke-Sqlcmd changes cases of uniqueidentifierInvoke-Sqlcmd 更改 uniqueidentifier 的情况
【发布时间】:2017-11-25 22:14:51
【问题描述】:

我正在尝试开发一个脚本,以根据 RFC 4180 定期导出格式正确的 CSV 文件。我正在使用 PowerShell 脚本来执行此操作,该脚本调用 Sqlcmd。但是,输出似乎改变了数据库中某些值的大小写。例如,uniqueidentifier 值从完全大写变为

92adbee2-adbf-de11-90b0-005056b325c4

我正在运行的仅输出到 powershell 终端的脚本如下。

Invoke-Sqlcmd -Query "SELECT top 10 * FROM 
dbo.Account;" `
-Database db_name `
-Server server-name `
-QueryTimeout 65535

有什么方法可以阻止这个工具改变类型为 uniqueidentifier 的值的大小写?

谢谢

【问题讨论】:

  • UniquIdentifier 不是字符串,它是一个 16 字节的十六进制数字。因此,字母大小写无关紧要。 aA 都等于十进制 10 或二进制 1010
  • @ZoharPeled 但我相信当输出到 csv 或 PowerShell 窗口时它会转换为字符串?我的问题是它可以将其导出为大写字符串吗?当我在管理工作室中运行相同的 sql 查询时,结果网格中显示的 uniqueidentifier 值是大写的,但使用 sqlcmd cmdlet 它们以小写形式返回。
  • 这只是字符串表示。它不会改变 guid 的值。
  • 字符串表示将在下游系统中使用,因此我需要 guid 的字符串表示在导出时保持一致,最好是大写。
  • 如果您需要它是大写的,那么只需将其分配给一个变量并使用.ToUpper() 命令。

标签: sql-server powershell sqlcmd invoke-sqlcmd


【解决方案1】:

正如一些 cmets 指出的,uniqueidentifier 实际上是一个二进制值,xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 只是二进制值的多种不同视觉表示之一。

在 SQL Server Management Studio 中,查询结果窗口使用带有大写十六进制数字的 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 布局来格式化唯一标识符。

SQL Server 中的 uniqueidentifier 类型映射到 PowerShell(即 .Net)中的 Guid 类型。默认的 .Net Guid.ToString 方法也使用 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 布局,但使用小写十六进制数字。

如果您可以覆盖 PowerShell 中的 Guid.ToString 方法,那么您可以更改使用的格式,但您不能这样做。如果您已经有一个用于处理 RFC 4180 特殊情况(引号、值中的分隔符等)的自定义表格格式化程序,那么您可以在其中添加 Guid 格式。

【讨论】:

    【解决方案2】:

    在 Powershell 中使用: $SQL_Command = "sqlcmd -S $DbServer -U $SQL_User -P $SQL_Pass -i $TSQL_File -o$CSV_OutPut_FileName -s ',' -w 65530"

    调用表达式 $SQL_Command

    第一个变量($SQL_Command)存放sqlcmd命令 Invoke-Expression cmdlet 计算或运行指定字符串作为命令

    $TSQL_File 变量是包含 sql 语句的文件名(例如:SELECT GUID FROM TableName....sql server 中的唯一标识符数据类型,或者您可以使用 SELECT * FROM TableName)

    输出不会改变 SQL Server 中 uniqueidentifier 数据类型的情况...希望有所帮助。

    sqlcmd 的语法
    -a 数据包大小
    -A(专用管理员连接)
    -b(如果出现错误则终止批处理作业)
    -c 批处理终结器
    -C(信任服务器证书)
    -d 数据库名称
    -e(回显输入)
    -E(使用可信连接)
    -f 代码页 | i:codepage[,o:codepage] | o:codepage[,i:codepage] -g(启用列加密) -G(使用 Azure Active Directory 进行身份验证) -h rows_per_header
    -H 工作站名称
    -i 输入文件
    -I(启用带引号的标识符)
    -j(打印原始错误消息) -k[1 | 2](删除或替换控制字符)
    -K application_intent
    -l 登录超时
    -L[c](列出服务器,可选的干净输出)
    -m 错误级别
    -M 多子网故障转移
    -N(加密连接)
    -o 输出文件
    -p[1](打印统计信息,可选冒号格式)
    -P 密码
    -q "命令行查询"
    -Q “命令行查询”(并退出)
    -r[0 | 1](消息到标准错误)
    -R(使用客户端区域设置)
    -s col_separator
    -S [协议:]服务器[实例名称][,端口]
    -t 查询超时
    -u(unicode 输出文件)
    -U 登录ID
    -v var = "值"
    -V error_severity_level
    -w 列宽
    -W(删除尾随空格)
    -x(禁用变量替换)
    -X[1](禁用命令、启动脚本、环境变量、可选退出)
    -y variable_length_type_display_width
    -Y 固定长度类型显示宽度
    -z 新密码
    -Z new_password(并退出)
    -? (用法)

    【讨论】:

    • 解释您在此处所做的事情对其他人会有所帮助。
    • 感谢您的建议。昨天赶时间没来得及解释。
    【解决方案3】:
    #----------------------------------------------------------------------------------------------------------   
    #--- Each line of TSQL_FileName.TXT ($ScriptsArray) contains a file name ($TSQL_File) of the TSQL statement that need to be execute
    #----------------------------------------------------------------------------------------------------------   
    FOREACH ($TSQL_File in $ScriptsArray)
    { $Num_TSQL_File++
      $Result_MSG = ''
      #----------------------------------------------------------------------------------------------------------   
      #--- GENERATE OUT PUT FILE NAME USE FOR CSV FILE WHEN WE RUN sqlcmd 
      #----------------------------------------------------------------------------------------------------------   
      $OutPut_File = (Get-Item $TSQL_File).Basename+'_'+$OutPut_DateTime
      $OutPut_File = $OutPut_File.replace(' ','_')
      $OutPut_File = $OutPut_File.replace('.','_')
      $OutPut_File = $OutPut_File+'.CSV'
      $OutPut_Error = ''
      $SQL_Command = "sqlcmd -S $DbServer -U $SQL_User -P $SQL_Pass -i $TSQL_File -o $OutPut_File -s ',' -w 65530"
      Invoke-Expression $SQL_Command 
      $OutPut_Array = Get-Content $OutPut_File
      $ThirdLine = "|"+$OutPut_Array[3]+"|"
      #----------------------------------------------------------------------------------------------------------
      #--- Determine if an error had occured, if so send email notification
      #----------------------------------------------------------------------------------------------------------
      IF (($OutPut_Array -like "Error*") -or ($OutPut_Array -like "Msg*") -or ($OutPut_Array -like "Invalid*")  -or ($OutPut_Array -like "Sqlcmd: Error*") )
      { $OutPut_Error = (Get-Item $TSQL_File).Basename+'_'+$OutPut_DateTime+'.ERR'
        $OutPut_Array | out-file ".\$OutPut_Error"
        $Result_MSG = 'Error!'
        $OutPut_File = $OutPut_Error
        $OutPut_FileSizeKb = $NumOfRow_Send = 0
        $global:DbErr++
        "{0,-16} {1,-40} {2,-60} {3,-10} {4,-4} {5,-4}" -f $DbServer, $TSQL_File, $OutPut_File, [int]$OutPut_FileSizeKb, $NumOfRow_Send, $Result_MSG
        $Results_Array += ,@($Results_Array_Index, $DbServer, $TSQL_File, $OutPut_File, $OutPut_FileSizeKb, $NumOfRow_Send, $Result_MSG)  
        $Results_Array_Index++
      }
      ELSE
      { #----------------------------------------------------------------------------------------------------------
        #--- Determine if zero row return from query, if so modify the array so that it will send only header info
        #----------------------------------------------------------------------------------------------------------
        IF ( ($OutPut_Array.Length -EQ 3) -and ($ThirdLine -EQ '||') )
        { $NeedFix_Array = Get-Content $OutPut_File
          #-------------------------------------------------------------
          #--- MODIFY THE ARRAY SO THAT IT WILL SEND ONLY THE HEADER
          #-------------------------------------------------------------
          $NeedFix_Array = $NeedFix_Array[1]
          #-----------------------------------------------------------
          #--- REMOVE BLANK SPACE FROM THE LINE
          #-----------------------------------------------------------
          $NeedFix_Array = $NeedFix_Array -replace '\s+', ' '
          $NeedFix_Array = $NeedFix_Array -replace ' ,', ','
          $NeedFix_Array = $NeedFix_Array -replace ', ', ','
          #-----------------------------------------------------------
          $NeedFix_Array | out-file $OutPut_File -Encoding ASCII
          $OutPut_FileSizeKb = (Get-Item $OutPut_File).length/1KB
          $OutPut_FileSizeKb = [int][Math]::Ceiling($OutPut_FileSizeKb)
          $NumOfRow_Send = 1
          $Num_CSV_File_Created++
          "{0,-16} {1,-40} {2,-60} {3,-10} {4,-4} {5,-4}" -f $DbServer, $TSQL_File, $OutPut_File, [int]$OutPut_FileSizeKb, $NumOfRow_Send, $Result_MSG
          $Results_Array += ,@($Results_Array_Index, $DbServer, $TSQL_File, $OutPut_File, $OutPut_FileSizeKb, $NumOfRow_Send, $Result_MSG)  
          $Results_Array_Index++
        }
        #----------------------------------------------------------------------------------------------------------
        #--- REMOVE 1st LINE AND '-----' IN 3rd LINE AND FIX THE SPACES BETWEEN COMMA
        #----------------------------------------------------------------------------------------------------------
        ELSE
        { $NeedFix_Array = Get-Content $OutPut_File
          #-------------------------------------------------------------
          #--- REMOVE THE FIRST LINE 
          #-------------------------------------------------------------
          $NeedFix_Array = $NeedFix_Array[1..($NeedFix_Array.Length-1)]
          #-------------------------------------------------------------
          #--- REMOVE THE SECOND LINE AFTER THE FIRST LINE WERE REMOVE
          #-------------------------------------------------------------
          $NeedFix_Array = $NeedFix_Array[0,0+2..($NeedFix_Array.length - 1)]
          $NeedFix_Array = $NeedFix_Array[1..($NeedFix_Array.Length-1)]
          #-----------------------------------------------------------
          #--- REMOVE BLANK SPACE FROM THE LINE
          #-----------------------------------------------------------
          $NeedFix_Array = $NeedFix_Array -replace '\s+', ' '
          $NeedFix_Array = $NeedFix_Array -replace ' ,', ','
          $NeedFix_Array = $NeedFix_Array -replace ', ', ','
          #-----------------------------------------------------------
          $NeedFix_Array | out-file $OutPut_File -Encoding ASCII
          $OutPut_FileSizeKb = (Get-Item $OutPut_File).length/1KB
          $OutPut_FileSizeKb = [int][Math]::Ceiling($OutPut_FileSizeKb)
          $NumOfRow_Send = $NeedFix_Array.Length
          $Num_CSV_File_Created++
          "{0,-16} {1,-40} {2,-60} {3,-10} {4,-4} {5,-4}" -f $DbServer, $TSQL_File, $OutPut_File, [int]$OutPut_FileSizeKb, $NumOfRow_Send, $Result_MSG
          $Results_Array += ,@($Results_Array_Index, $DbServer, $TSQL_File, $OutPut_File, $OutPut_FileSizeKb, $NumOfRow_Send, $Result_MSG)  
          $Results_Array_Index++
        }
      }
    }`enter code here`
    

    【讨论】:

      猜你喜欢
      • 2016-09-07
      • 1970-01-01
      • 2016-05-11
      • 1970-01-01
      • 2016-01-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 2017-08-03
      相关资源
      最近更新 更多