Импорт csv файла в базу данных MS SQL
Если CSV файлик 500 МБ, его необходимо перенести в таблицу базы данных.
Один из возможных способов это использовать PoweShell скрипт для чтения csv файла и передачи данных в базу.
Прежде необходимо убедится, что файл использует UTF-8 кодировку. Так как после добавления данных в базу, если не перекодировать файл, могут отображаться крякозябры вместо кириллицы.
План
- Перекодировать исходный файл в UTF-8 кодировку
- Импорт в базу данных по 50 тыс. записей за одну итерацию
- Перекодировать файл в другую кодировку
Это можно реализовать через PoweShell.
В коде заменить входной файл и исходящий.
Входной файл - $inFile
Выходной файл - $outFile . Файл будет создан автоматически.
В месте GetEncoding(1251) укажите Вашу исходную кодировку. В данном случае WIN-1251
$inFile = 'D:\Temp\_2579.csv' $outFile = 'D:\Temp\_2579_powershell_encoding.csv' $reader = New-Object IO.StreamReader ($inFile, [Text.Encoding]::GetEncoding(1251)) $writer = New-Object IO.StreamWriter ($outFile, $false, [Text.Encoding]::UTF8) while ($reader.Peek() -ge 0) { $writer.WriteLine($reader.ReadLine()) } $reader.Close(); $reader.Dispose() $writer.Close(); $writer.Dispose()
Сохраните результат в формате *.ps1
Запустите powershell с правами администратора.
Перейдите в директорию, где сохранён скрипт.
Пример: cd D:\Temp\
Введите название скрипта с приставкой .\
Получится: .\powerchell_encoding_file.ps1 (можно начать писать название файла и нажать TAB )
Нажать Enter
Всё файл готов. В указанном месте $outFile будет создать файл с кодировкой UTF-8.
- Запись данных в базу данных
Для записи данных, в первую очередь, необходимо создать таблицу, в которую будут перемещены данные.
Количество и названия колонок должны быть идентичными тем, которые находятся в CSV файле.
Следующим етапом будет создание PoweShell скрипта.
# Database variables $sqlserver = "SQL" $database = " Bundle " $table = " Bundle.dbo.[_import_Utf-8]" $UserId = "User1" $Password = "Pass1" # CSV variables $csvfile = "D:\Temp\_2579_powershell_encoding.csv" $csvdelimiter = ";" $firstRowColumnNames = $true ################### No need to modify anything below ################### Write-Host "Script started..." $elapsed = [System.Diagnostics.Stopwatch]::StartNew() [void][Reflection.Assembly]::LoadWithPartialName("System.Data") [void][Reflection.Assembly]::LoadWithPartialName("System.Data.SqlClient") # 50k worked fastest and kept memory usage to a minimum $batchsize = 50000 # Build the sqlbulkcopy connection, and set the timeout to infinite $connectionstring = "Data Source=$sqlserver; User ID = $UserId; Password = $Password; Initial Catalog=$database;" $bulkcopy = New-Object Data.SqlClient.SqlBulkCopy($connectionstring, [System.Data.SqlClient.SqlBulkCopyOptions]::TableLock) $bulkcopy.DestinationTableName = $table $bulkcopy.bulkcopyTimeout = 0 $bulkcopy.batchsize = $batchsize # Create the datatable, and autogenerate the columns. $datatable = New-Object System.Data.DataTable # Open the text file from disk $reader = New-Object System.IO.StreamReader($csvfile) $columns = (Get-Content $csvfile -First 1).Split($csvdelimiter) if ($firstRowColumnNames -eq $true) { $null = $reader.readLine() } foreach ($column in $columns) { $null = $datatable.Columns.Add() } # Read in the data, line by line while (($line = $reader.ReadLine()) -ne $null) { $null = $datatable.Rows.Add($line.Split($csvdelimiter)) $i++; if (($i % $batchsize) -eq 0) { $bulkcopy.WriteToServer($datatable) Write-Host "$i rows have been inserted in $($elapsed.Elapsed.ToString())." $datatable.Clear() } } # Add in all the remaining rows since the last clear if($datatable.Rows.Count -gt 0) { $bulkcopy.WriteToServer($datatable) $datatable.Clear() } # Clean Up $reader.Close(); $reader.Dispose() $bulkcopy.Close(); $bulkcopy.Dispose() $datatable.Dispose() Write-Host "Script complete. $i rows have been inserted into the database." Write-Host "Total Elapsed Time: $($elapsed.Elapsed.ToString())" # Sometimes the Garbage Collector takes too long to clear the huge datatable. [System.GC]::Collect()
В первом блоке заполняем информацию для подключения к SQL-серверу:
$sqlserver = "SQL" - Название SQL-сервера
$database = " Bundle " - База данных
$table = "Bundle.dbo.[_import_Utf-8]" - Таблица
$UserId = "User1" - Логин
$Password = "Pass1" - Пароль
В следующем блоке заполняем информацию о CSV-файле
$csvfile = "D:\Temp\_2579_powershell_encoding.csv" - Расположение файла
$csvdelimiter = ";" - разделитель
$firstRowColumnNames = $true - Есть ли название колонок в файле?
Сохраняем в формате *.ps1. Запускаем через PowerShell.
Полезные ресурсы
- https://blog.netnerds.net/2015/01/powershell-high-performance-techniques-for-importing-csv-to-sql-server/#comment-50531 – страница с powershell скриптом
- https://stackoverflow.com/questions/41392833/encoding-csv-content-to-utf-8 - перекодировка файла
- https://2cyr.com/decode/ – онлайн декодер