ساعدني في استخدام PowerShell و BCP لتحميل CSV في SQL Server

StackOverflow https://stackoverflow.com/questions/3526368

  •  29-09-2019
  •  | 
  •  

سؤال

أنا أستخدم BCP لتحميل جدول من CSV تم تصديره من جدول آخر من قبل شخص آخر بعيدًا ، وواجهت بعض المشكلات. مشكلتي الأصلية: أحد الحقل المصدر هو int يحتاج إلى أن ينتهي به المطاف في حقل varchar ، ويجب ملء حقل آخر بسلسلة ثابتة. حسنًا ، الأول ليس صفقة كبيرة ، وقادني إجابة تشاد إلى @{n='Col3';e={'ABC'}} بناء الجملة. لكنني أتعثر حول العديد من المشكلات في تحميل البيانات بشكل صحيح.

  1. في بعض الأحيان ، قد لا يكون للقيمة مسافات ، في بعض الأحيان قد يكون ذلك. كيف يمكنني تحديد المحددات لذلك في ملف تنسيق BCP؟ أسأل لأنني من المفترض أنني بحاجة إلى المحيط بها مع اقتباسات.

    أ. هل يجب أن أرفق القيم في ملف CSV الوسيط مع علامات الاقتباس؟

  2. في رمز الاختبار الخاص بي ، يقوم بدفع رؤوس الأعمدة و Linefeed إلى 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, ، و تفاح داخل 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
هل كانت مفيدة؟

المحلول

لماذا لا تستخدم SQLBulkcopy من ADO.NET برمجياً في PowerShell؟ سيكون لديك تحكم كامل: اقرأ الخط من السطر ، وتحويل البيانات وملء بيانات قابلة للتصميم كما يحلو لك وتستدعي WriteToServer على دفعات. نرى http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

نصائح أخرى

يمكنك أن تفعل شيئًا كهذا لإضافة العمود

Import -CSV. Forum.CSV -Header "Col1" ، "Col2" ، "Col4" | حدد Col1 ، Col2 ، @{n = 'col3' ؛ e = {'export1'}} ، col4 | Export -CSV ./forum2.csv -notypeinfo

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top