Sql-Server

dbatools 導入 csv 幫助!

  • August 30, 2022

有沒有辦法可以使用 PS dba 工具將具有正確數據類型的csv文件導入 MSSQL 表?

我正在使用以下命令,但我得到的只是一個表,所有列都是 nvarchar(max):

Import-DbaCsv -Path C:\user.csv -SqlInstance $server -Database $DB -AutoCreateTable

我知道我可以通過 SSIS 實現這一點,但這對我來說不是最佳選擇,因為某些 CSV 結構不斷變化,+/- 列。

您的案例中的根本問題是批量載入器無法正確猜測列大小甚至數據類型。您會看到,在大多數 ETL 實現中,列類型和長度都是提前指定的。載入程序可以相信數據要麼適合目的地,要麼將其歸類為損壞的數據。

載入程序無法知道,例如,第 501 行在產品描述中有很長的 1500 個字元的字元串,而所有其他行只有幾十個字母。如果它猜測該列較短,則第 501 行將無法正確載入。如果它安全且使一切順利nvarchar(max),則數據適合但效率低下並且不進行類型檢查。

現在,載入程序可以讀取整個文件併計算每一列的最大長度和數據類型。然後它可以根據這些規範創建一個表。然後它會再次讀取整個文件,並進行插入。這將需要兩次讀取文件,這是低效的並且通常不需要,因為 ETL 過程依賴於預先同意的文件格式。一些工具,例如 SQL Server Management Studio 的導入嚮導,可以做到這一點。它從文件中讀取前 200 行,並根據該數據進行猜測。這就是為什麼我建議不匹配的數據位於第 501 行,離採樣器組件太遠了。

有一些工具,例如csvkit,可以從 CSV 文件創建表結構。好不好用,我沒有經驗。

對於Import-DbaCsv,請參閱參數的幫助文本-ColumnMap

預設情況下,大容量複製嘗試自動映射列…

對於具有可變列標題的 CSV 文件,Import-DbaCsv將最好地猜測映射到哪裡(因此列名和數據類型很重要)。

自己展示一下。

use tempdb
go
drop table if exists foo;
create table dbo.foo (
    id int not null primary key identity
   ,foo varchar(100) 
   ,bar int 
   ,baz date
   ,bin varchar(100) 
);

foo.csv注意和列的區別foo2.csv

@"
foo,bar,baz
aaa,111,1900-01-01
bbb,222,1900-02-02
ccc,333,1900-03-03
"@ | Set-Content foo.csv

@"
foo,bin,baz
ddd,444,1900-01-04
eee,555,1900-02-05
fff,666,1900-03-06
"@ | Set-Content foo2.csv

$importSpec = @{
   SqlInstance = "localhost"
   Database    = "tempdb"
   Schema      = "dbo"
   Table       = "foo"
}

Import-DbaCsv foo.csv @importSpec -Verbose
Import-DbaCsv foo2.csv @importSpec -Verbose
select * from tempdb.dbo.foo;

請注意,列已正確映射到數據庫目標中


免責聲明:我編寫了 AutoMap 邏輯的 v1,儘管從那時起它發生了變化。

引用自:https://dba.stackexchange.com/questions/316219