私は現在、データを SQL に取り込むさまざまな方法で遊んでいます。昨日、BCP を使用して問題に遭遇しました。これは解決しましたが、あまり役に立たないエラー情報のために SSIS パッケージを使用していることを思い出しました。私が好きな作業方法では、データ行全体をステージング テーブルに (BCP または一括挿入を使用して) 固定幅または区切りでロードし、データ行を強制的に型指定するよりも操作する方がはるかに幸せだと思います。 SQL への途中の列。
そのため、データを宛先に挿入する前にデータを分割して検証 (データ型をチェック) し、不良データ行を別のテーブルに書き出すことができるアプローチを見つけて、それらをどうするかを決定できるようにしたいと考えています。 .
シナリオをシミュレートするスクリプトを作成しました。importedData テーブルは、BCP または BULK INSERT の出力になります。ImportedData からのすべてのデータは、最終的に Presenters または RejectedData テーブルのいずれかに入る必要があります。
かなりうまくスケーリングできるアプローチが必要です。実際の状況では、2,000 万行のデータを含む 40 列のようなものになる可能性があるため、一度に 10,000 行を処理するようなことをしなければならないと考えています。
SQL Server 2012 にはおそらく役立つ新しい try_parse 関数がありますが、2005 および 2008 マシンでこれを実行できるようにする必要があります。
IF OBJECT_ID (N'ImportedData', N'U') IS NOT NULL DROP TABLE dbo.ImportedData
CREATE TABLE dbo.ImportedData (RowID INT IDENTITY(1,1), DataRow VARCHAR(MAX))
IF OBJECT_ID (N'Presenters', N'U') IS NOT NULL DROP TABLE dbo.Presenters
CREATE TABLE dbo.Presenters (PresenterID INT, FirstName VARCHAR(10), LastName VARCHAR(10))
IF OBJECT_ID (N'RejectedData', N'U') IS NOT NULL DROP TABLE dbo.RejectedData
CREATE TABLE dbo.RejectedData (DataRow VARCHAR(MAX))
-- insert as fixed-width
INSERT INTO dbo.ImportedData(DataRow)
SELECT '1 Bruce Forsythe '
UNION ALL SELECT '2 David Dickinson '
UNION ALL SELECT 'X BAD DATA'
UNION ALL SELECT '3 Keith Chegwin '
-- insert as CSV
/*INSERT INTO dbo.ImportedData(DataRow)
SELECT '1,Bruce,Forsythe'
UNION ALL SELECT '2,David,Dickinson'
UNION ALL SELECT 'X,BAD,DATA'
UNION ALL SELECT '3,Keith,Chegwin'
*/
---------- DATA PROCESSING -------------------------------
SELECT
SUBSTRING(DataRow,1,3) AS ID,
SUBSTRING(DataRow,4,10) AS FirstName,
SUBSTRING(DataRow,14,10) AS LastName
FROM
ImportedData
---------- DATA PROCESSING -------------------------------
SELECT * FROM ImportedData
SELECT * FROM Presenters
SELECT * FROM RejectedData