Помогите мне использовать powershell и bcp для загрузки CSV в SQL Server

Я использую bcp для загрузки таблицы из CSV, экспортированной из другой таблицы кем-то еще далеко, и столкнулся с некоторыми проблемами. Мои исходные две проблемы: одно экспортируемое поле - это int, которое должно оказаться в поле varchar, а другое поле необходимо заполнить статической строкой. Что ж, первое не имеет большого значения, и ответ Чада привел меня к синтаксису @{n='Col3';e={'ABC'}}. Но я натыкаюсь на несколько проблем с правильной загрузкой данных.

  1. Иногда значение может не содержать пробелов, иногда может. Как мне указать разделители для этого в файле формата bcp? Я спрашиваю, потому что, по-видимому, мне нужно заключить их в кавычки.

    а. Следует ли заключать значения в промежуточный файл CSV в кавычки?

  2. В моем тестовом коде заголовки столбцов и перевод строки помещаются в Col1 с фактическим значением Col1 для первой строки.

  3. В моем фактическом, необработанном коде я получаю String data, right truncation в первой строке, хотя вторая строка вставлена ​​нормально.

Во всяком случае, исходные данные CSV, которые я получаю откуда-то, выглядят так (примечание: нет строки заголовка)

"ABC123",123456,"APPLE"
"XYZ789",456789,"ORANGE"

Целевая таблица SQL выглядит так

Col1 varchar(50) (Primary Key)
Col2 varchar(50)
Col3 varchar(50)
Col4 varchar(50)

Мне нужно загрузить ABC123 в Col1, 123456 в Col2, Export1 в Col3 и APPLE в Col4. Export1 - статическая строка. Я делаю это в Powershell 1.0.

РЕДАКТИРОВАТЬ: импорт CSV Чада | export-csv выглядит многообещающе, но ему не нравятся пропущенные заголовки, а PS 1.0 не поддерживает параметр -Header.

РЕДАКТИРОВАТЬ: отредактированное описание выше, чтобы отразить, как я дошел до этого момента. Таблица с четырьмя столбцами и CSV с тремя столбцами явно упрощены. Один настоящий столбец - это город, поэтому он может содержать простые строки или строки, требующие цитирования. Мой код Powershell 1.0 на данный момент выглядит следующим образом.

$SQLSERVER="svr"
$SQLTABLE="test"
$SQLUSER="u"
$SQLPASS="p"

$TESTFILE = "testdata.csv"
$TESTFILEHDR = "testdata-wHeaders.csv"
$TESTFILEFIX = "testdata-fixed.csv"
$OrigHeaders = "`"Col1`",`"Col2`",`"Col3`"`n"

function Create-BcpFormat($fileName)
{
@"
<?xml version='1.0'?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <RECORD>
  <FIELD ID='1' xsi:type='CharTerm' TERMINATOR=',"' COLLATION='SQL_AltDiction_CP850_CI_AS'/>
  <FIELD ID='2' xsi:type='CharTerm' TERMINATOR='",' COLLATION='SQL_AltDiction_CP850_CI_AS'/>
  <FIELD ID='3' xsi:type='CharTerm' TERMINATOR=',' COLLATION='SQL_AltDiction_CP850_CI_AS'/>
  <FIELD ID='4' xsi:type='CharTerm' TERMINATOR='\r\n' COLLATION='SQL_AltDiction_CP850_CI_AS'/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="1" NAME="Col1" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="2" NAME="Col2" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="3" NAME="Col3" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="4" NAME="Col4" xsi:type="SQLVARYCHAR"/>
 </ROW>
</BCPFORMAT>
"@ | Set-Content $filename
}

## GHI456 is already in the table, clean out previous attempts
"`nclean test table:"
osql @("-S","$SQLSERVER","-U","$SQLUSER","-P","$SQLPASS","-Q",
    """delete from $SQLTABLE where col1 <> 'GHI456' or col1 is null""")

## Prepend
$body = [string]::join([environment]::NewLine, (gc $TESTFILE))
$OrigHeaders + $body > $TESTFILEHDR

"`nTESTFILEHDR:"
type $TESTFILEHDR

$accts = Import-csv $TESTFILEHDR | select 'Col1', 'Col2', @{n='Col3';e={'ABC'}}, @{n='Col4';e={$_.Col3}}
$accts
$accts | Export-Csv $TESTFILEFIX -NoTypeInfo

"`nTESTFILEFIX:"
type $TESTFILEFIX

$BCPFMTFILE = "bcp.fmt"
$BCPERRFILE = "bcp.err"
Create-BcpFormat $BCPFMTFILE
bcp @("$SQLTABLE","in","$TESTFILEFIX","-S","$SQLSERVER","-U","$SQLUSER","-P","$SQLPASS","-f",$BCPFMTFILE,"-e",$BCPERRFILE)
Remove-Item $BCPFMTFILE

"`ntest table:"
osql @("-S","$SQLSERVER","-U","$SQLUSER","-P","$SQLPASS","-Q",
    """select left(Col1,20) 'Col1', left(Col2,8) 'Col2', left(Col3,8) 'Col3', left(Col4,8) 'Col4' from $SQLTABLE""")

"`nBCPERRFILE:"
type $BCPERRFILE

person b w    schedule 19.08.2010    source источник


Ответы (2)


Почему вы не используете SqlBulkCopy ADO.NET программно в PowerShell? У вас будет полный контроль: читать построчно, конвертировать данные и заполнять DataTable по своему усмотрению, а также запускать WriteToServer партиями. См. http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

person vaso    schedule 24.08.2010
comment
Благодарю. Это приблизило меня к ответу. В итоге я создал файл sqlcmd со вставками в PowerShell, но вы избавили меня от мысли, что ответом был bcp. В массовой копии утверждалось, что у меня нет разрешения. В любом случае, хотя sqlcmd работает, я планирую возиться с решением ADO.NET. Спасибо! - person b w; 24.08.2010
comment
Рад, что это помогло Вот пример того, как создать необходимые объекты if ($ global: systemDataAssembly -eq $ null) {[Reflection.Assembly] $ global: systemDataAssembly = [Reflection.Assembly] :: LoadWithPartialName (System.Data); } [System.Data.SqlClient.SqlBulkCopy] $ local: bulkCopy = New-Object -TypeName System.Data.SqlClient.SqlBulkCopy -ArgumentList Источник данных =. \ SQLEXPRESS; Интегрированная безопасность = да; Начальный каталог = test; $ local: bulkCopy.DestinationTableName = dbo.test; [System.Data.DataTable] $ local: dataTable = New-Object -TypeName System.Data.DataTable; # вот и настоящие действия - person vaso; 25.08.2010
comment
извините, форматирование пошло не так. Еще не освоил. В комментариях вроде по другому работает. - person vaso; 25.08.2010

Вы можете сделать что-то вроде этого, чтобы добавить столбец

import-csv. \ forum.csv -Header "Col1", "Col2", "Col4" | Выберите Col1, Col2, @ {n = 'Col3'; e = {'Export1'}}, Col4 | Экспорт-CSV ./forum2.csv -NoTypeInfo

person Chad Miller    schedule 19.08.2010
comment
вы имеете в виду создать промежуточный CSV, а затем bcp это в SQL? - person b w; 20.08.2010
comment
Если вы хотите обновить исходный файл csv, используйте это: (import-csv. \ Forum.csv -Header Col1, Col2, Col4) | Выберите Col1, Col2, @ {n = 'Col3'; e = {'Export1'}}, Col4 | Экспорт-CSV ./forum.csv -NoTypeInfo - person Chad Miller; 20.08.2010
comment
это было полезно, так что +1, но это не привело меня туда. Однако ответ был оценен по достоинству! - person b w; 24.08.2010