设置要在PowerShell export-csv中使用的日期格式?

时间:2013-02-16 11:49:42

标签: powershell

我正在尝试将数据库表导出为文本(CSV-ish)以用于以后的BULK INSERT。 使用ISO格式yyyy-mm-dd的日期会少得多。我相信,我最终说服SQL Server Express在其导入中期望英国格式(尽管灰色的服务器属性被卡在“英语(美国)”中,无论我做什么)。我将用户帐户更改为英国,这与我的PowerShell CSV导出格式相对应。 但我宁愿使用ISO格式来解决问题。

目前,已填写SELECT * FROM Table的表变量并将其传输到Export-CSV,日期将在生成的文本文件中以dd/mm/yyyy格式显示。

如何强制PowerShell脚本在所有语句中使用ISO格式日期(即每个命令中没有指定格式),因此Export-CSV会将它们写为I需要?我一直在圈子里看了几个小时看“文化”和事物,但我完全糊涂了!

3 个答案:

答案 0 :(得分:7)

尝试格式化您的文化:

PS C:\> $(get-date).ToShortDateString()
2/16/2013
PS C:\> $(Get-Culture).DateTimeFormat.ShortDatePattern = 'yyyy-MM-dd'
PS C:\> $(get-date).ToShortDateString()
2013-02-16

答案 1 :(得分:0)

非常感谢jbockle的帮助,我现在可以从办公室(SQL server 2005)将数据带回家,并将其导入到运行SQL Server 2008 Express的家用Win XP机器上的相同表格(来自CREATE .sql脚本)。 / p>

在第一个示例中,表格直接导出为CSV,然后进行清理。 Convert-Line函数删除“引号,因为BULK INSERT不喜欢它们,并且还在每行的开头和结尾添加额外的反引号分隔符,以便它可以用True替换任何1和任何False 0(在线上的任何地方),因为布尔是棘手的:) (它似乎与相邻的布尔人有问题,所以这个传球跑两次将它们全部拖了!) 最后一行修剪了从开始和放大的不需要的`每行结束。

##  PowerShell newbies : for scripts to run, you must first execute:  Set-ExecutionPolicy RemoteSigned
##  and then all scripts will work (it's a global setting, remembered once run)

$SQLDT = New-Object "System.Data.DataTable"
$path = "C:"
(Get-Culture).DateTimeFormat.ShortDatePattern="yyyy-MM-dd"   # temp setting, for dates in ISO format

function Convert-Line
{  param( [string]$line=$(throw 'a CSV line is required.'))
  ## add ` to start and end, combined with removing quotes
   $line = "``" + $line + "``" -replace "`"", ""
  ## swap Boolean True/False to 1 or 0
  ##  !! Need to do it twice, as it has trouble with adjacent ones!!
   $line = $line -replace "``True``","``1``" -replace "``False``","``0``"
   $line = $line -replace "``True``","``1``" -replace "``False``","``0``"
  ## return with trimmed off start/end delimiters
   $line.TrimStart("``").TrimEnd("``")
}

function Table-Export
{   param( [string]$table=$(throw 'table is required.'))

   ## Get whole SQL table into $SQLDT datatable
    $sqldt.reset()
    $connString = "Server=.\SQLEXPRESS;Database=Test1;Integrated Security=SSPI;"
    $da = New-Object "System.Data.SqlClient.SqlDataAdapter" ("select * from $table",$connString)
    [void]$da.fill($SQLDT)

   ## Export to CSV with ` delimiter
    $sqldt | Export-Csv $path\$table.CSV -NoTypeInformation -delimiter "``"

   ## read entire file, parse line by line, process line, write back out again
    (gc $path\$table.CSV) | Foreach-Object { Convert-Line -line $_ } | Set-Content $path\$table.CSV
}

# main...
Table-Export -table "Table1"
Table-Export -table "Table2"
Table-Export -table "Table3etc"

使用SQL

很好地导入
DELETE FROM table1;
BULK INSERT table1 FROM 'C:\table1.csv' WITH (KEEPIDENTITY, FIELDTERMINATOR = '`');
DELETE FROM table2;
BULK INSERT table2 FROM 'C:\table2.csv' WITH (KEEPIDENTITY, FIELDTERMINATOR = '`');
-- etc, all tables

保留原始标识字段以使表连接仍然有效。

适用于字段类型:数字,文本,布尔值,日期。

BULK INSERT会抱怨包含字段名称的第一行,但这是一个可忽略的警告(不要因为它不起作用而试图FIRSTROW = 2)。

在第二个示例中,采用了另一种方法 - 这次将DataTable复制到一个新列,其中每列都是字符串类型,以便可以调整每个字段而不会出现类型问题。然后将复制数据表导出为CSV,然后我们需要做的就是处理它以删除不需要的双引号。

这次我们有机会替换“在任何字符串字段中,所以双引号或逗号都不会打破它们,例如像John这样的名字”JJ“史密斯最终将成为约翰'JJ'史密斯,这有望被接受。

$SQLDT = New-Object "System.Data.DataTable"
$path = "C:"
(Get-Culture).DateTimeFormat.ShortDatePattern="yyyy-MM-dd"   # temp setting, for dates in ISO format

function Table-Export
{   param( [string]$table=$(throw 'table is required.'))

   ## Get whole SQL table into $SQLDT datatable
    $sqldt.reset()
    $connString = "Server=.\SQLEXPRESS;Database=Test1;Integrated Security=SSPI;"
    $da = New-Object "System.Data.SqlClient.SqlDataAdapter" ("select * from $table",$connString)
    [void]$da.fill($SQLDT)

   ## Copy $SqlDt DataTable to a new $DT2 copy, with all columns now String type
    $DT2 = New-Object "System.Data.DataTable"
    $sqldt.columns | Foreach-Object { $DT2.Columns.Add($_.Caption) > $null }

   ## copy all $SqlDt rows to the new $DT2
   ## and change any " double quote in any field to a ' single quote, to preserve meaning in text fields
   ##  ( or you could use an odd char and replace in SQL database later, to return to " )
    For($i=0;$i -lt $sqldt.Rows.Count;$i++)
    { $DT2.Rows.Add() > $null
      For($i2=0;$i2 -lt $sqldt.Columns.Count;$i2++)
      { $DT2.Rows[$i][$i2] = $SQLDT.Rows[$i][$i2] -replace "`"","'" }
    }

  ## If any $SqlDt column was Boolean...
  ## use column name.. and for all rows in the new $DT2 : convert True/False to 1/0
   $sqldt.columns | Foreach-Object {
     If ($_.DataType.Name -EQ "Boolean")
     { $ColName = $_.Caption
       For($i=0;$i -lt $sqldt.Rows.Count;$i++)
       { If ($DT2.Rows[$i][$ColName] -EQ "True") { $DT2.Rows[$i][$ColName]="1" }
         If ($DT2.Rows[$i][$ColName] -EQ "False") { $DT2.Rows[$i][$ColName]="0" }
       }
     }
   }

   ## Export to CSV with ` delimiter
    $DT2 | Export-Csv $path\$table.CSV -NoTypeInformation -delimiter "``"

   ## read entire file, parse line by line, remove all ", write back out again
   (gc $path\$table.CSV) | Foreach-Object {$_ -replace "`"", "" } | Set-Content $path\$table.CSV
}

# main...
Table-Export -table "Table1"
Table-Export -table "Table2"
Table-Export -table "Table3etc"

Emtpy表不会破坏这个脚本,你只需要一个零字节的CSV文件。

答案 2 :(得分:0)

仅供参考我使用PowerShell将BULK插入SQL中做了很多工作,我发现解决问题的最简单方法是:

  1. 使用Export-Csv -Delimited“t”将数据导出为CSV - 这是制表符分隔文件。
  2. 批量插入时,插入到将所有列设置为NVARCHAR(MAX)数据类型的临时表中。
  3. 创建一个设置了正确数据类型的第二个临时表。
  4. 从Temp Table 1到Temp Table 2中选择记录,在SQL中使用REPLACE命令替换所有引号,无需任何引号。
  5. 当我遇到一个包含其自身数据中的选项卡的列时,这只会让我感到沮丧,但是如果我遇到它们,我只需用这些列中的空格替换选项卡。

    当我处理包含数千行的CSV文件时,这是我能做到的最简单的方法,并且速度最快,因为它基于所有设置。