web-dev-qa-db-ja.com

一括挿入-(0行が影響を受けました)

一括挿入を使用して.CSVファイルをmssqlテーブルにインポートしようとしています(他の方法は開いていますが)。一括挿入SQ​​Lステートメントがありますが、ファイルを実行すると(0行が影響を受けました)と表示されます。ただし、ファイル自体にデータがあります。

サンプルCSVファイル(ヘッダー+ヘッダーの下の1行)


。CSVヘッダー

changedate、deactivate、lockout、noemail、empno、orighire、salary、salut、fname、mi、lname、username、hstreet1、hstreet2、hcity、hstate、hcountry、hzip、busphone、busext、cellular、empemail、jobtitle、jobcode、jobgroup、 orglevel1、orglevel2、orglevel3、orglevel4、orglevel5、company、perfdate、supervisor、misc1、misc2、misc3、misc4、active

。CSVコンテンツ

2014-04-03 00:00:00、いいえ、いいえ、いいえ、1133、2014-04-03 00:00:00、1111.1111 、、テスト、テスト、テスト、user.test、111テスト方法、、サクラメント、 CA、USA、11111 , test @ test.org、test test、057,02、sss、261、SAC , test、ttt、1911-11-11 00:00:00,1111、N , test 、0、NULL


。SQL

BULK
INSERT dbo.Archive
FROM 'C:\scripts\User.csv'
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\r\n',
FIRSTROW = 2
)
GO

私はpsを通してこれを達成しようとしました、そしてこれは結果とコードでした:

# Database variables
$sqlserver = "dbserver"
$database = "db"
$table = "tb"

# CSV variables
$csvfile = "C:\scripts\User.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;Integrated         Security=true;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()

[〜#〜]エラー[〜#〜]

PS C:\ scripts> C:\ scripts\Import-CSVtoSQL.ps1スクリプトが開始しました... "1"引数を指定して "WriteToServer"を呼び出す例外: "cold 38のbcpクライアントから無効な列長を受け取りました。" C:\ scripts\Import-CSVtoSQL.ps1:51 char:2 + $ bulkcopy.WriteToServer($ datatable)+ ~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~ + CategoryInfo:NotSpecified:(:) []、MethodInvocationException + FullyQualifiedErrorId:SqlException

5
Bytesized

インポートしようとしているテーブルに、追加の列があります。つまり、Datestampbatch number。問題は、csvファイルよりもテーブルに多くあることです。 csvで定義された列のみがあり、機能する一時テーブルにインポートしました。

1
Bytesized

元の質問には\n\rは行の終了記号として。 Windowsでは、行の終了記号は通常\r\n、キャリッジリターンを最初に、ラインフィードを2番目に使用します(あいまいですが興味深い歴史的な理由から)。 BULK INSERTコマンド。

次に、16進エディタでファイルをロードして、改行の正確な内容を検証します。たとえば、データがUnicodeの場合、\0\r\0\nをセパレータとして、および/またはDATAFILETYPE ='widechar' 国旗。注意 0x0Aは10進数の10、0x0Dは10進数13です。ASCII改行コード(\n)と復帰(\r)、それぞれ。

1

追加してみてくださいERRORFILE = 'file_name'をwith句に追加して、答えが現れるかどうかを確認します。 (または少なくともエラー。)通常は、最大MAXERRORSエラーが発生し、良好な行があっても停止します。

0
Seeds

次のいずれかを行うことができます。

  • セッションベース、インスタンスベース、スキーマベースのいずれであっても、データを取得するための一時テーブルを作成します。 または
  • 1-1をマップする列を含むビューを作成します。

最適なソリューション

レコードに必要なすべてのリビングデータとメタデータを含むテーブルを用意します。

CREATE TABLE [STAGE].[File](
    [RowID] [bigint] IDENTITY(1,1) NOT NULL,
    [AUDIT_BatchUID] [uniqueidentifier] NULL,
    [FileID] [uniqueidentifier] NULL,
    [RowData] [varchar](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

ファイルからのデータの「受信者」になるために必要なフィールドのみを使用して、そのテーブルのビューを作成します。

CREATE VIEW [STAGE].[vw_File]
AS
SELECT        RowData
FROM            STAGE.[File]

Bulk Insertビューに。私はたまたま動的SQLベースですが、アイデアはそこにあります。

declare @stmt varchar(max)
select @stmt = '
    bulk insert stage.vw_File
    from ''' + @fileandpath + '''
    with (
        FirstRow = ' + @firstRow + ',
        RowTerminator = ''' + @rowTerminator + '''
    )
'

一括挿入後、適切なメタデータを使用してテーブルデータをサニタイズします。

0
GoldBishop

インポートをブロックする可能性のあるものは、宛先のフィールドも短すぎます。たとえば、50文字のフィールドがソースに51文字あります。しかし、実際には、無効な文字を伝えるメッセージが各行に表示されます(実際にははっきりとはわかりません)。

0
Gloops