1

我正在尝试开发一个脚本,以根据 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 类型的值的大小写?

谢谢

4

3 回答 3

0

在 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 packet_size
-A(专用管理员连接)
-b(如果出现错误则终止批处理作业)
-c batch_terminator
-C(信任服务器证书)
-d db_name
-e(回显输入)
-E(使用信任连接)
-f 代码页 | i:codepage[,o:codepage] | o:codepage[,i:codepage] -g(启用列加密) -G(使用 Azure Active Directory 进行身份验证) -h rows_per_header
-H 工作站名称
-i input_file
-I(启用带引号的标识符)
-j(打印原始错误消息) -k[1 | 2](删除或替换控制字符)
-K application_intent
-l login_timeout
-L[c] (列出服务器,可选的干净输出)
-m error_level
-M multisubnet_failover
-N (加密连接)
-o output_file
-p[1] (打印统计,可选冒号格式)
-P password
-q "cmdline query"
-Q “命令行查询”(并退出)
-r[0 | 1] (msgs to stderr)
-R (使用客户端区域设置)
-s col_separator
-S [protocol:]server[instance_name][,port]
-t query_timeout
-u (unicode output file)
-U login_id
-v var = " value"
-V error_severity_level
-w column_width
-W (删除尾随空格)
-x(禁用变量替换)
-X[1](禁用命令、启动脚本、环境变量、可选退出)
-y variable_length_type_display_width
-Y fixed_length_type_display_width
-z new_password
-Z new_password(并退出)
-? (用法)

于 2018-05-23T20:03:59.343 回答
0
#----------------------------------------------------------------------------------------------------------   
#--- 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`
于 2018-05-25T15:29:23.043 回答
0

正如一些评论指出的那样,唯一标识符实际上是一个二进制值,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 格式。

于 2018-05-23T23:06:33.793 回答