关于您的主要问题:“我有没有办法使用这种方法,但将字段设置为正确的格式,以便它们可以进入正确定义的 sql 表?”是的。 p>
您可以在创建 DataTable 之前将值转换为所需的类型(下面的示例代码)。就个人而言,我可能会尝试将 CSV 文件替换为对类型信息进行编码的内容,例如 JSON 或 parquet。
根据 OP 的问题更新:
我必须拼出该循环中的每个字段,还是只拼出需要从字符串更改为其他内容的字段?
您必须将每个字段映射到[PSCustomObject],但您只需要转换包含非字符串数据的字段。
对于有空格的列标题,在 PS 中引用它们时是否用括号括起来(如 [Created on Date])
我调整了答案以说明一种处理带有空格的列标题的方法。请参见“e e”列。
我看到您的示例将 0.2 类型数字转换为“double”。
我的十进制数据将是货币,并将与其他数据一起使用,以便我将其设置为十进制。您是否期望这会正常流动,或者是否有不同的正确语法可以转换为十进制?
根据下面的参考,.NET 的十进制类型应该映射到 SQL Server 的十进制类型。请参阅示例数据中的属性 f。
https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-data-type-mappings
假设您在 CSV 中有以下数据
a,b,c,d,e e,f
string1,1,0.1,2020-05-02 14:29:06.780,e,1.99
string2,2,0.2,2020-05-03 01:01:02.000,e,3.59
您可以使用类似于下面foreach 循环中的方法将值转换为所需的类型。显然,您必须对其进行自定义以适合您的实际数据。
param(
$datasource = 'localhost',
$db = 'test',
$destTable = 'table',
$csvPath = "$PSScriptRoot\data.csv"
)
$ConnectionString = "Data Source=$datasource; Database=$db;Trusted_Connection=True;";
. "$PSScriptRoot\Out-DataTable.ps1"
$rawData = Import-CSV -Path $csvPath
$typedData = @()
foreach ($row in $rawData) {
$tempObj = [PSCustomObject] @{
a = $row.a
b = [int] $row.b
c = [double] $row.c
d = [datetime] $row.d
e_e = $row."e e"
f = [decimal] $row.f
}
$typedData += $tempObj
}
$csvDataTable = $typedData | Out-DataTable
$bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $ConnectionString
$bulkCopy.DestinationTableName = $destTable
$bulkCopy.WriteToServer($csvDataTable)
Out-DataTable.ps1 的内容(供未来读者使用)
#######################
function Get-Type {
param($type)
$types = @(
'System.Boolean',
'System.Byte[]',
'System.Byte',
'System.Char',
'System.Datetime',
'System.Decimal',
'System.Double',
'System.Guid',
'System.Int16',
'System.Int32',
'System.Int64',
'System.Single',
'System.UInt16',
'System.UInt32',
'System.UInt64')
if ( $types -contains $type ) {
Write-Output "$type"
}
else {
Write-Output 'System.String'
}
} #Get-Type
#######################
<#
.SYNOPSIS
Creates a DataTable for an object
.DESCRIPTION
Creates a DataTable based on an objects properties.
.INPUTS
Object
Any object can be piped to Out-DataTable
.OUTPUTS
System.Data.DataTable
.EXAMPLE
$dt = Get-psdrive| Out-DataTable
This example creates a DataTable from the properties of Get-psdrive and assigns output to $dt variable
.NOTES
Adapted from script by Marc van Orsouw see link
Version History
v1.0 - Chad Miller - Initial Release
v1.1 - Chad Miller - Fixed Issue with Properties
v1.2 - Chad Miller - Added setting column datatype by property as suggested by emp0
v1.3 - Chad Miller - Corrected issue with setting datatype on empty properties
v1.4 - Chad Miller - Corrected issue with DBNull
v1.5 - Chad Miller - Updated example
v1.6 - Chad Miller - Added column datatype logic with default to string
v1.7 - Chad Miller - Fixed issue with IsArray
.LINK
http://thepowershellguy.com/blogs/posh/archive/2007/01/21/powershell-gui-scripblock-monitor-script.aspx
#>
function Out-DataTable {
[CmdletBinding()]
param([Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] [PSObject[]]$InputObject)
Begin {
$dt = new-object Data.datatable
$First = $true
}
Process {
foreach ($object in $InputObject) {
$DR = $DT.NewRow()
foreach ($property in $object.PsObject.get_properties()) {
if ($first) {
$Col = new-object Data.DataColumn
$Col.ColumnName = $property.Name.ToString()
if ($property.value) {
if ($property.value -isnot [System.DBNull]) {
$Col.DataType = [System.Type]::GetType("$(Get-Type $property.TypeNameOfValue)")
}
}
$DT.Columns.Add($Col)
}
if ($property.Gettype().IsArray) {
$DR.Item($property.Name) = $property.value | ConvertTo-XML -AS String -NoTypeInformation -Depth 1
}
else {
$DR.Item($property.Name) = $property.value
}
}
$DT.Rows.Add($DR)
$First = $false
}
}
End {
Write-Output @(, ($dt))
}
} #Out-DataTable