Импорт 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/ – онлайн декодер