2

GeoLiteCountryMaxmind から CSV ファイルをダウンロードしました - http://www.maxmind.com/app/geolitecountry。標準として与えられた形式を使用して(これが自動化されたタスクになるように)、すべてのデータをテーブルにインポートしようとしています。

IPCountries2提供された列と正確に一致する列を持つ新しいテーブルを作成しました。

FromIP       varchar(50),
ToIP         varchar(50),
BeginNum     bigint,
EndNum       bigint,
CountryCode  varchar(50),
CountryName  varchar(250)

見つけたさまざまなコードのチャンクを使用して、フィールド ターミネーターと行ターミネーターを使用して動作させることができませんでした。

BULK
INSERT CSVTest
FROM 'c:\csvtest.txt'
WITH
(
    FIELDTERMINATOR = '","',
    ROWTERMINATOR = '\n'
)
GO

この結果、単一の行が挿入されました。最後の行が次の行でオーバーフローしたことを除いて、すべて正しいです (制限がなければ、おそらくデータベース全体)。また、最初のセルの先頭に引用符がありました。

私は周りを見回して、フォーマットファイルと呼ばれるものを見つけました(これらを使用したことはありません)。次のようなものを作りました:

10.0
6
1   SQLCHAR     0   50  "," 1   FromIP      ""
2   SQLCHAR     0   50  "," 2   ToIP        ""
3   SQLBIGINT   0   19  "," 3   BeginNum    ""
4   SQLBIGINT   0   19  "," 4   EndNum      ""
5   SQLCHAR     0   50  "," 5   CountryCode ""
6   SQLCHAR     0   250 "\n"    6   CountryName ""

しかし、bigint行でのこのエラー:

メッセージ 4867、レベル 16、状態 1、行 1
行 1、列 3 (BeginNum) の一括読み込みデータ変換エラー (オーバーフロー)。

それを 10 回実行し、最大エラー数のために停止します。

最初の方法をExcelに取り込んで再保存すると、最初の方法が機能するようになりました。これにより、引用符が削除されました。ただし、これを毎週自動的に更新し、手動で開いて再保存する必要がないため、この方法に依存したくありません。

クリーンなファイルで動作する限り、2 つの方法のどちらを最終的に使用してもかまいません。ドキュメントを見てみましたが、PHP または MS Access のコードしかありません。

編集

CSV ファイルの一部の行:

"1.0.0.0","1.0.0.255","16777216","16777471","AU","Australia"
"1.0.1.0","1.0.3.255","16777472","16778239","CN","China"
"1.0.4.0","1.0.7.255","16778240","16779263","AU","Australia"
"1.0.8.0","1.0.15.255","16779264","16781311","CN","China"
"1.0.16.0","1.0.31.255","16781312","16785407","JP","Japan"
"1.0.32.0","1.0.63.255","16785408","16793599","CN","China"
"1.0.64.0","1.0.127.255","16793600","16809983","JP","Japan"
"1.0.128.0","1.0.255.255","16809984","16842751","TH","Thailand"
"1.1.0.0","1.1.0.255","16842752","16843007","CN","China"
"1.1.1.0","1.1.1.255","16843008","16843263","AU","Australia"
"1.1.2.0","1.1.63.255","16843264","16859135","CN","China"
"1.1.64.0","1.1.127.255","16859136","16875519","JP","Japan"
"1.1.128.0","1.1.255.255","16875520","16908287","TH","Thailand"

アップデート

しばらく粘った後、元の方法で(フォーマットドキュメントなしで)95%動作させることができました。ただし、次のように少し変更されました。

BULK INSERT IPCountries2
FROM 'c:\Temp\GeoIPCountryWhois.csv'
WITH
(
    FIELDTERMINATOR = '","',
    ROWTERMINATOR = '"'
)
GO

すべてが適切なフィールドに正しく配置されます。唯一の問題は、最初の列の最初に引用があることです。いくつかのサンプルデータ:

FromIP  ToIP    BeginNum    EndNum  CountryCode Country
 "2.21.248.0    2.21.253.255    34994176    34995711    FR  France
 "2.21.254.0    2.21.254.255    34995712    34995967    EU  Europe
 "2.21.255.0    2.21.255.255    34995968    34996223    NL  Netherlands
4

3 に答える 3

2

成功。周りを検索し、別のフォーラムからの助けを借りて、ようやく私の解決策にたどり着きました。同様の解決策を必要としている人のために、読み続けてください:

私は最終的にフォーマットファイル方式を使用しました-フィールドターミネータと行ターミネータを使用できるかどうかはわかりません。

私のSQLコードは次のようになります。

CREATE TABLE #TempTable
(
    DuffColumn  varchar(50),
    FromIP      varchar(50),
    ToIP        varchar(50),
    BeginNum    bigint,
    EndNum      bigint,
    CountryCode varchar(50),
    CountryName varchar(250)
)

BULK
INSERT #TempTable
FROM 'c:\Temp\GeoIPCountryWhois.csv'
WITH
(
    FORMATFILE = 'C:\Temp\format.fmt'
)

INSERT INTO IPCountries2 (FromIP, ToIP, BeginNum, EndNum, CountryCode, Country)
    SELECT FromIP, ToIP, BeginNum, EndNum, CountryCode, CountryName FROM #TempTable

私の研究でわかったように、最初の引用を単純にとらえた役に立たないコラムが必要でした。

私のフォーマットファイルは次のようになります:

10.0
7
1   SQLCHAR     0   1   ""      1   DuffColumn  ""
2   SQLCHAR     0   50  "\",\"" 2   FromIP      ""
3   SQLCHAR     0   50  "\",\"" 3   ToIP        ""
4   SQLCHAR     0   19  "\",\"" 4   BeginNum    ""
5   SQLCHAR     0   19  "\",\"" 5   EndNum      ""
6   SQLCHAR     0   50  "\",\"" 6   CountryCode ""
7   SQLCHAR     0   250 "\"\n"  7   CountryName ""

注意すべき点として、最終的にBIGINTとして格納されるにもかかわらず、BeginNumとEndNumは両方ともSQLCHARSとして渡されます。そうでない場合、挿入は数値に対して奇妙な乗算を行います(数字ではなくバイトとして読み取ることについての何か、私はそれを完全には理解していませんでした) 。

そしてそれはそれについてです。このスクリプトを完全に自動化する最後のことは、古いレコードをクリアするために最初にテーブルを切り捨てることです。しかし、それはすべての人のニーズに当てはまるとは限りません。

于 2012-03-26T09:15:12.507 に答える
0

このコマンドを試してください。私がしたことは、FIELDTERMINATOR から二重引用符を削除することだけです。

BULK
INSERT CSVTest
FROM 'c:\csvtest.txt'
WITH
(
    FIELDTERMINATOR = ',',
    ROWTERMINATOR = '\n'
)
GO

データ フィールドは、引用符で囲まれたコンマではなく、実際にはコンマで終了します。また、ソース ファイルのデータ型と正確に一致するステージング/インポート テーブルを作成することをお勧めします。この場合は次のようになります。

FromIP       varchar(50),
ToIP         varchar(50),
BeginNum     varchar(50),
EndNum       varchar(50),
CountryCode  varchar(50),
CountryName  varchar(250)

BeginNum と EndNum のソース データは、実際には bigint ではなく文字列です。ステージング テーブルにインポートすると、このデータを変換できます。

于 2012-03-20T16:49:45.563 に答える