web-dev-qa-db-ja.com

一度に複数のテーブルに挿入する

2つのデータベース間でデータを移行しています。最初のデータベースから、次の列を持つcsvファイルをエクスポートしています。

Customer_Name
Contact_First_Name
Contact_Last_Name
Phone1
Phone2
Fax

このデータを取得して、新しいデータベースの次のテーブルに配置する必要があります。

Table: customer_contact
    contact_id  INT IDENTITY(1,1)
    first_name  VARCHAR(50)
    last_name   VARCHAR(50)
    customer_id INT
    PK = contact_id

Table: contact_phone
    contact_id INT
    phone_num  VARCHAR(15)
    in_use     BIT
    PK = contact_id, phone_num

Table: contact_fax
    contact_id INT
    fax_num    VARCHAR(15)
    in_use     BIT
    PK = contact_id, fax_num

私の計画はBULK INSERT csvからのデータを一時テーブルに格納し、それを使用して他の各テーブルにINSERTsを実行します。

各連絡先のメインの識別子は姓と名の場合、対応するデータを電話とFAXのテーブルに挿入するにはどうすればよいですか? SQL Serverを使用しています。

2
Skitzafreak

このソリューションは、CSVでデータを繰り返しており、すべてのケースで何をするかを制御したい場合に適用されます。以下のフィールドについての質問には何もないので、それらのロジックは含めません。

customer_id INT, 
in_use     BIT

0-質問ですでに宣言したテーブルを作成します

1-cvsの正確な構造を持つt_Bulkテーブルを作成し、一括コピーを実行します

CREATE TABLE T_BULK (
Customer_Name VARCHAR(100),
Contact_First_Name VARCHAR(50),
Contact_Last_Name VARCHAR(50),
Phone1 VARCHAR(15),
Phone2 VARCHAR(15),
Fax VARCHAR(15)
);
GO

2-T_BULKテーブルがすでにいっぱいになっている状態で、各レコードを処理してみましょう。

DECLARE @ContactId int, @FirstName varchar(50), @LastName varchar(50), @Phone1 varchar(50), @Phone2 varchar(50), @Fax varchar(50)

    DECLARE MY_CURSOR CURSOR 
    LOCAL STATIC READ_ONLY FORWARD_ONLY  
    FOR   
    SELECT Contact_First_Name, Contact_Last_Name, Phone1, Phone2, Fax
    FROM dbo.T_BULK


    OPEN MY_CURSOR  
    FETCH NEXT FROM MY_CURSOR INTO @FirstName, @LastName, @Phone1, @Phone2, @Fax
    WHILE @@FETCH_STATUS = 0  
    BEGIN   

    //if the contact already exists we get the identity
    IF EXISTS (select contact_id from customer_contact where first_name=@FirstName and last_name=@LastName)
        select @ContactId = contact_id from customer_contact where first_name=@FirstName and last_name=@LastName

    //if the contact does not exit we need to insert and retrieve the new Identity value
    ELSE
        BEGIN
            insert customer_contact (first_name,last_name) values (@FirstName,@LastName)
            set @ContactId = SCOPE_IDENTITY()
        END

    //now we continue with the phones and fax
    //insert only new phones
    INSERT contact_phone (contact_id,phone_num) 
    SELECT Id, Phone   
    FROM (select @ContactId as Id, @Phone1 as Phone UNION select @ContactId ,@Phone2) P  
    WHERE NOT EXISTS (SELECT * FROM contact_phone C WHERE C.contact_id = P.Id and C.phone_num = P.Phone); 

    //insert only new fax
    INSERT contact_fax (contact_id,fax_num) 
    SELECT Id, fax   
    FROM (select @ContactId as Id, @Fax as fax) F
    WHERE NOT EXISTS (SELECT * FROM contact_fax C WHERE C.contact_id = F.Id and C.fax_num = F.fax); 


        FETCH NEXT FROM MY_CURSOR INTO @FirstName, @LastName, @Phone1, @Phone2, @Fax  
    END  

    CLOSE MY_CURSOR  
    DEALLOCATE MY_CURSOR

幸運を

追加フィールドを含めるには:

宣言ゾーンに追加の変数を含めます:@Extension

両方に含める必要がありますFETCH NEXT行。次に、電話を挿入するときにその変数を含める必要がありますが、この場合は、電話が重複していないことを確認するために、phone2がphone1と等しくないことを確認する必要があります。

    (select @contactId as Id, @Phone1 as Phone, @Extension as Extension 
UNION select @ContactId, @Phone2, null where @Phone2 <>@Phone1) P
1
AMG

[〜#〜] bcp [〜#〜]を使用する場合は、KEEPIDENTITYを使用する必要があります。これにより、一括挿入SQL Serverが提供する自動インクリメントではなく、既存のID値を使用します。

また、最終的なテーブルに挿入する前にステージングテーブルを使用します。これにより、データの整合性とフォーマットを検証します。

https://docs.Microsoft.com/en-us/sql/relational-databases/import-export/keep-identity-values-when-bulk-importing-data-sql-server?view=sql-サーバー-2017

0
Eduardo Pivaral

これは、CSVファイルにデータの問題がないと想定してタスクを実行する方法です。 first_name、last_nameは、個人を一意に識別すると想定します。たとえば、1人につき1行です...

1Xロード

  1. Bulkinsertを介して、CSVファイルを必要な列を含むステージテーブルにロードします。

STG_Contactsを 'c:\ contacts.csv'から一括挿入(FIELDTERMINATOR = '、'、ROWTERMINATOR = '\ n')

  1. ステージテーブルからcustomer_contactテーブルに挿入する

-customer_idを生成する方法がわからないため、デフォルトでnullにしてください

customer_contactに挿入(first_name、last_name、customer_id)STG_ContactsからCustomer_IDとしてContact_First_Name、Contact_LastName、NULLを選択します

  1. contact_phoneテーブルに挿入

-デフォルトの電話1からtrue電話2からfalse ??

contact_phone(contact_id、phone_num、in_use)select b.contact_id、a.Phone1、 'True' from InUse from STG_Contacts a join customer_contact b on a.Contact_First_Name = b.first_name and a.Contact_Last_Name = b.last_name where(Phone1 is not nullおよびlen(Phone1)> 0)union all select b.contact_id、a.Phone2、 'False' from InUse from STG_Contacts a join customer_contact b on a.Contact_First_Name = b.first_name and a.Contact_Last_Name = b.last_name where( Phone2はnullではなく、len(Phone2)> 0)

  1. fAXテーブルに挿入する

contact_fax(contact_id、fax_num、in_use)に挿入b.contact_id、a.fax、 'True' as InUse from STG_Contacts a join customer_contact b on a.Contact_First_Name = b.first_name and a.Contact_Last_Name = b.last_name where(fax_num is nullではなく、len(fax_num)> 0)

Nightly loading ... SSISまたはTSQLを介してSQLエージェントを介して

  1. ステージングテーブルを切り捨てます
  2. Csv w/bulk insertからステージングテーブルを読み込む
  3. 連絡先テーブルに新しい行を読み込み、更新を処理する
  4. 電話とFAXテーブルに新しい行を読み込み、更新を処理する

マージステートメントを使用して新しい行、更新、削除を処理する方法については、この link を使用してください。

0
Goforebroke