1

ある DB から別の DB にデータを移行する必要があります。SqlBulkCopy を使用することを選択しましたが、ソース データベースの照合順序が宛先データベースと異なるため、問題が発生しました。例外があります。

System.InvalidOperationException: The locale id '1049' of the source column 'Id' and the locale id '1033' of the destination column 'Id' do not match.
   at System.Data.SqlClient.SqlBulkCopy.AnalyzeTargetAndCreateUpdateBulkCommand(BulkCopySimpleResultSet internalResults)
   at System.Data.SqlClient.SqlBulkCopy.WriteToServerInternal()
   at System.Data.SqlClient.SqlBulkCopy.WriteRowSourceToServer(Int32 columnCount)
   at System.Data.SqlClient.SqlBulkCopy.WriteToServer(IDataReader reader)
   at MigrateToNormalized.DirectMapCommand.Migrate(SqlConnection source, SqlConnection destination, SqlTransaction transaction) in D:\Projects\APS\DTE\MigrateTo
Normalized\MigrateToNormalized\MigrateToNormalized\DirectMapCommand.cs:line 53
   at MigrateToNormalized.Program.Main(String[] args) in D:\Projects\APS\DTE\MigrateToNormalized\MigrateToNormalized\MigrateToNormalized\Program.cs:line 32

SQLクエリでCOLLATEステートメントを直接使用せずにこの問題を解決する方法を教えてもらえますか? ソース データベースのすべての列の照合順序を変更する簡単な方法はありますか?

4

4 に答える 4

3

SqlBulkCopy を使用すると、エラーが発生することがあります。これは、SqlBulkCopy を使用しているときに列をマップする最良の方法です。

私の以前のコード:

SqlConnectionStringBuilder cb = new SqlConnectionStringBuilder("Data Source=ServerName;User Id=userid;Password=****;Initial Catalog=Deepak; Pooling=true; Max pool size=200; Min pool size=0");
SqlConnection con = new SqlConnection(cb.ConnectionString);
SqlCommand cmd = new SqlCommand("select Name,Class,Section,RollNo from Student", con);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
SqlBulkCopy sbc = new SqlBulkCopy("Data Source=DestinationServer;User Id=destinationserveruserid;Password=******;Initial Catalog=DeepakTransfer; Pooling=true; Max pool size=200; Min pool size=0");
sbc.DestinationTableName = "StudentTrans";   
sbc.WriteToServer(rdr); 
sbc.Close();
rdr.Close();
con.Close();

コードは私に次のようなエラーを与えていました:

ソース列 'RollNo' のロケール ID '0' と宛先列 'Section' のロケール ID '1033' が一致しません。

列のマッピング後、コードが正常に実行されます。

私の変更されたコードは次のとおりです。

SqlConnectionStringBuilder cb = new SqlConnectionStringBuilder("Data Source=ServerName;User Id=userid;Password=****;Initial Catalog=Deepak;");
SqlConnection con = new SqlConnection(cb.ConnectionString);
SqlCommand cmd = new SqlCommand("select Name,Class,Section,RollNo from Student", con);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
SqlBulkCopy sbc = new SqlBulkCopy("Data Source=DestinationServer;User Id=destinationserveruserid;Password=******;Initial Catalog=DeepakTransfer;");
sbc.DestinationTableName = "StudentTrans";
sbc.ColumnMappings.Add("Name", "Name");
sbc.ColumnMappings.Add("Class", "Class");
sbc.ColumnMappings.Add("Section", "Section");
sbc.ColumnMappings.Add("RollNo", "RollNo");
sbc.WriteToServer(rdr);
sbc.Close();
rdr.Close();
con.Close();

このコードは正常に実行されています。

于 2011-11-24T12:45:46.547 に答える
2

照合順序が異なる列を選択できます。

SELECT Foo COLLATE SQL_Latin1_General_CP1_CI_AS AS Bar FROM Baz

これにより、列 Foo の照合が新しい照合に変換されます。上記の例では、列Fooが照合に変換され、クエリでBarSQL_Latin1_General_CP1_CI_ASという名前が付けられます。

次に、bulkcopy コマンドの新しい列に列マッピングを追加する必要があります。

using (var bulkCopy = new SqlBulkCopy(connection))
{
    bulkCopy.DestinationTableName = "FooBars";
    bulkCopy.ColumnMappings.Add("Bar", "FooBar"); 
    bulkCopy.WriteToServer(reader);
}
于 2012-03-29T12:17:49.350 に答える
1

単純な列マッピングの追加はうまくいきませんでした。そして、SqlBulkCopy と DataTable を介して挿入を実装しました - これは正常に動作します。

private void BulkCopyTable(string sourceConnection, string targetConnection, Table sTable, Table tTable)
{
    using (SqlConnection sourceConn = new SqlConnection(sourceConnection))
    {
        if (cbFixStructure.Checked)
            CheckAndRecreateTarget(targetConnection, sTable, tTable);

        string selectSql = "SELECT * FROM " + sTable.Schema + ".[" + sTable.Name + "]";

        string selectCntSql = "SELECT COUNT(*) FROM " + sTable.Schema + ".[" + sTable.Name + "] WITH(NOLOCK)";
        using (SqlCommand selectCmd = new SqlCommand(selectSql, sourceConn))
        {
            selectCmd.CommandTimeout = 60 * 100 * 1000;
            sourceConn.Open();
            Int64 totalCount = 0;
            using (SqlCommand cntCommand = new SqlCommand(selectCntSql, sourceConn))
            {
                cntCommand.CommandTimeout = 60 * 100 * 1000;
                totalCount = Convert.ToInt64(cntCommand.ExecuteScalar());
            }

            DataTable dtBuffer = new DataTable();
            var columns = sTable.Columns.Cast<Column>().Where(p => p.Computed == false).ToList();
            foreach (var clm in columns)
            {
                var sdt = clm.DataType.SqlDataType;
                if (sdt == SqlDataType.UserDefinedDataType)
                {
                    var lst = Enum.GetValues(typeof(SqlDataType)).Cast<SqlDataType>();
                    sdt = lst.Where(p => p.ToString().ToLower() == TargetDataBase.UserDefinedDataTypes[clm.DataType.Name].SystemType.ToString()).First();
                }

                dtBuffer.Columns.Add(new DataColumn(clm.Name, GetClrType(sdt)));
            }
            using (SqlDataReader reader = selectCmd.ExecuteReader())
            {
                using (SqlBulkCopy blkCopy = new SqlBulkCopy(targetConnection, SqlBulkCopyOptions.KeepIdentity))
                {
                    blkCopy.BulkCopyTimeout = 60 * 100 * 1000;
                    blkCopy.DestinationTableName = sTable.Schema + ".[" + sTable.Name + "]";

                    foreach (var colmn in columns)
                    {
                        blkCopy.ColumnMappings.Add(colmn.Name, colmn.Name);
                    }

                    int bufferCountLengthMax = 500;
                    int rowCnt = 0;
                    int globalCounter = 0;
                    while (reader.Read())
                    {
                        var dataRow = dtBuffer.NewRow();
                        foreach (var clm in columns)
                        {
                            dataRow[clm.Name] = reader[clm.Name];
                        }
                        dtBuffer.Rows.Add(dataRow);
                        rowCnt++;
                        globalCounter++;
                        if (rowCnt >= bufferCountLengthMax)
                        {
                            dtBuffer.AcceptChanges();
                            blkCopy.WriteToServer(dtBuffer);
                            rowCnt = 0;
                            dtBuffer.Rows.Clear();
                            GC.Collect();
                            DoLogText(String.Format("Table \"{0}\" copied rows {1} out of {2}", sTable.Schema + ".[" + sTable.Name + "]", globalCounter, totalCount));
                        }
                    }
                    if (rowCnt > 0)
                    {
                        dtBuffer.AcceptChanges();
                        blkCopy.WriteToServer(dtBuffer);
                        rowCnt = 0;
                        dtBuffer.Rows.Clear();
                        GC.Collect();
                        DoLogText(String.Format("Table \"{0}\" copied rows {1} out of {2}", sTable.Schema + ".[" + sTable.Name + "]", globalCounter, totalCount));
                    }
                }
            }
        }
    }
    DoLogText(String.Format("Table \"{0}\" done", sTable.Name));
}
于 2016-03-04T15:23:24.743 に答える
0

sqlbulkcopy に使用しているテーブルの列の照合順序を変更できます。

例えば

CREATE TABLE T3
(
    C1 int PRIMARY KEY,
    C2 varchar(50) NULL,
    C3 int NULL,
    C4 int 
) ;
GO

ALTER TABLE T3 ALTER COLUMN C2 varchar(50) COLLATE Latin1_General_BIN 
于 2010-12-13T17:44:13.203 に答える