非常感谢 jbockle 的帮助,我现在可以将数据从办公室(SQL Server 2005)带回家,并将其导入到我家运行 SQL Server 2008 Express 的 Win XP 机器上的相同表中(来自 CREATE .sql 脚本)。
在第一个示例中,表直接导出为 CSV,然后进行清理。Convert-Line 函数删除 " 引号,因为 BULK INSERT 不喜欢它们,并且还在每行的开头和结尾添加额外的反引号分隔符,以便它可以替换 any True
with1
和 any False
with 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" Smith 这样的名字最终会变成 John 'JJ' Smith,希望这是可以接受的。
$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"
空表不会破坏这个脚本,你只会得到一个零字节的 CSV 文件。