web-dev-qa-db-ja.com

ID(自動インクリメント)列を使用した一括挿入

CSVファイルからデータベースにバルクデータを追加しようとしています。

従業員表には、ID(PK)列が自動インクリメントされます。

CREATE TABLE [dbo].[Employee](
 [id] [int] IDENTITY(1,1) NOT NULL,
 [Name] [varchar](50) NULL,
 [Address] [varchar](50) NULL
) ON [PRIMARY]

私はこのクエリを使用しています:

BULK INSERT Employee  FROM 'path\tempFile.csv ' 
WITH (FIRSTROW = 2,KEEPIDENTITY,FIELDTERMINATOR = ',' , ROWTERMINATOR = '\n');

.CSVファイル-

Name,Address
name1,addr test 1
name2,addr test 2

ただし、次のエラーメッセージが表示されます。

行2、列1(id)の一括読み込みデータ変換エラー(指定されたコードページの型の不一致または無効な文字)。

67
Abhi

realテーブルに直接INSERTしないでください。

私はいつも

  1. cSVファイルからステージングテーブルdbo.Employee_StagingIDENTITY列なし)に挿入します
  2. インポートしたデータを編集/クリーンアップ/操作する可能性がある
  3. 次のようなT-SQLステートメントを使用して、データを実際のテーブルにコピーします。

    INSERT INTO dbo.Employee(Name, Address) 
       SELECT Name, Address
       FROM dbo.Employee_Staging
    
41
marc_s

Id列をcsvファイルに追加し、空白のままにします。

id,Name,Address
,name1,addr test 1
,name2,addr test 2

クエリからKEEPIDENTITYキーワードを削除します。

BULK INSERT Employee  FROM 'path\tempFile.csv ' 
WITH (FIRSTROW = 2,FIELDTERMINATOR = ',' , ROWTERMINATOR = '\n');

Id IDフィールドは自動インクリメントされます。

Csvのidフィールドに値を割り当てた場合、KEEPIDENTITYキーワードを使用しない限り無視され、自動インクリメントの代わりに使用されます。

97
Josh Werts

同様の問題がありましたが、IDの順序がソースファイルの順序と一致していることを確認する必要がありました。私の解決策は、一括挿入にビューを使用しています:

テーブルをそのままにして、このビューを作成します(ID列を除くすべてを選択します)

CREATE VIEW [dbo].[VW_Employee]
AS
SELECT [Name], [Address]
FROM [dbo].[Employee];

BULK INSERTは次のようになります。

BULK INSERT [dbo].[VW_Employee] FROM 'path\tempFile.csv ' 
WITH (FIRSTROW = 2,FIELDTERMINATOR = ',' , ROWTERMINATOR = '\n');
26
Paul_S

フォーマットファイルで一括挿入を行う必要があります。

   BULK INSERT Employee FROM 'path\tempFile.csv ' 
   WITH (FORMATFILE = 'path\tempFile.fmt');

フォーマットファイル(tempFile.fmt)は次のようになります。

11.0
2
1 SQLCHAR 0 50 "\ t" 2名前SQL_Latin1_General_CP1_CI_AS
2 SQLCHAR 0 50 "\ r\n" 3 Address SQL_Latin1_General_CP1_CI_AS

詳細はこちら- http://msdn.Microsoft.com/en-us/library/ms179250.aspx

7
hotfusion

私の解決策は、IDフィールドをテーブルのLASTフィールドとして追加することです。したがって、一括挿入はそれを無視し、自動値を取得します。清潔でシンプルな...

たとえば、一時テーブルに挿入する場合:

CREATE TABLE #TempTable 
(field1 varchar(max), field2 varchar(max), ... 
ROW_ID int IDENTITY(1,1) NOT NULL)

ROW_IDフィールドは常にLASTフィールドとして指定しなければならないことに注意してください!

2
Langbaba

私はこのまったく同じ問題を抱えていたため、損失時間が発生したので、自分に合った発見と解決策を共有したいと思います。

1。Excelファイルを使用

これが私が採用したアプローチです。 csvファイルを使用する代わりに、以下のような内容のExcelファイル(.xlsx)を使用しました。

id  username   email                token website

    johndoe   [email protected]        divostar.com
    bobstone  [email protected]        divosays.com

Id列には値がないことに注意してください。

次に、Microsoft SQL Server Management Studioを使用してDBに接続し、データベースを右クリックしてインポートデータを選択します(タスクの下のサブメニュー)。ソースとしてMicrosoft Excelを選択します。 「ソーステーブルとビューの選択」というステージに到達したら、マッピングの編集をクリックします。宛先の下のid列については、それをクリックしてignoreを選択します。別のデータベースからデータをインポートする場合にIDを保持し、ソースDBの自動インクリメントIDを維持したい場合を除き、Enable Identity insertをチェックしないでください。仕上げに進み、それで終わりです。データはスムーズにインポートされます。

2。CSVファイルを使用

Csvファイルで、データが以下のようになっていることを確認してください。

id,username,email,token,website
,johndoe,[email protected],,divostar.com
,bobstone,[email protected],,divosays.com

以下のクエリを実行します。

BULK INSERT Metrics FROM 'D:\Data Management\Data\CSV2\Production Data 2004 - 2016.csv '
WITH (FIRSTROW = 2, FIELDTERMINATOR = ',', ROWTERMINATOR = '\n');

このアプローチの問題は、CSVがDBサーバーまたはDBがアクセスできる共有フォルダーにある必要があることです。そうしないと、「ファイルを開けません。オペレーティングシステムがエラーコード21を返しました。 )」。

リモートデータベースに接続している場合、CSVをそのサーバーのディレクトリにアップロードし、一括挿入でパスを参照できます。

。CSVファイルとMicrosoft SQL Server Management Studioインポートオプションを使用

最初のアプローチのようにインポートデータを起動します。ソースについては、フラットファイルソースを選択し、CSVファイルを参照します。正しいメニュー([全般]、[列]、[詳細]、[プレビュー])に問題がないことを確認してください。列メニュー(列区切り文字)で正しい区切り文字を設定してください。上記のExcelのアプローチと同様に、マッピングの編集をクリックします。宛先の下のid列については、それをクリックしてignoreを選択します。

仕上げに進み、それで終わりです。データはスムーズにインポートされます。

1
Fokwa Best
  1. Identity列と他の列を含むテーブルを作成します。
  2. その上にビューを作成し、一括挿入する列のみを公開します。
  3. ビューのBCP
0
user10513964

別のオプションは、ステージングテーブルの代わりに一時テーブルを使用している場合、インポートが期待するとおりに一時テーブルを作成し、インポート後にID列を追加することです。

だからあなたのSQLは次のようなことをします:

  1. 一時テーブルが存在する場合、ドロップします
  2. 一時テーブルを作成する
  3. 一時テーブルへの一括インポート
  4. 一時テーブルの変更IDの追加
  5. <データでやりたいこと>
  6. 一時テーブルの削除

まだあまりきれいではありませんが、別のオプションです...安全のためにロックを取得する必要があるかもしれません。

0
Izzy

これは非常に古い答えの投稿ですが、与えられた答えのいずれも、提起された条件を変更せずに問題を解決するものではありません。

BULK INSERTのOPENROWSETバリアントを使用して解決しました。これは同じ形式のファイルを使用し、同じように機能しますが、データファイルをSELECTステートメントで読み取ることができます。

テーブルを作成します。

CREATE TABLE target_table(
id bigint IDENTITY(1,1),
col1 varchar(256) NULL,
col2 varchar(256) NULL,
col3 varchar(256) NULL)

コマンドウィンドウを開いて実行します。

bcp dbname.dbo.target_table format nul -c -x -f C:\format_file.xml -t; -T

これにより、テーブルの外観に基づいてフォーマットファイルが作成されます。

ここでフォーマットファイルを編集し、FIELD ID = "1"およびCOLUMN SOURCE = "1"の行全体を削除します。これはデータファイルに存在しないためです。
データファイルに必要なターミネータも調整します。

<?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="2" xsi:type="CharTerm" TERMINATOR=";" MAX_LENGTH="256" COLLATION="Finnish_Swedish_CI_AS"/>
  <FIELD ID="3" xsi:type="CharTerm" TERMINATOR=";" MAX_LENGTH="256" COLLATION="Finnish_Swedish_CI_AS"/>
  <FIELD ID="4" xsi:type="CharTerm" TERMINATOR="\r\n" MAX_LENGTH="256" COLLATION="Finnish_Swedish_CI_AS"/>
 </RECORD>
 <ROW>
  <COLUMN SOURCE="2" NAME="col1" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="3" NAME="col2" xsi:type="SQLVARYCHAR"/>
  <COLUMN SOURCE="4" NAME="col3" xsi:type="SQLVARYCHAR"/>
 </ROW>
</BCPFORMAT>

これで、selectを使用してデータファイルをテーブルに一括読み込みできるため、列を完全に制御できます。この場合、ID列にデータを挿入しないでください。

INSERT INTO target_table (col1,col2, col3)
SELECT * FROM  openrowset(
bulk 'C:\data_file.txt',
formatfile='C:\format_file.xml') as t;
0
whetstone