2017-07-04 14 views
2

私は、SQL DBから読み込んでMySQLに書き込むアプリケーションを持っています。このアプリは、クライアントのデータを移行するために使用されます。テスト中に私は単一のレコードで問題が発生していると私は困惑しています。私はC#Encodingクラスの使用に関してこのサイトからのさまざまな提案をテストし、この単一のレコードで成功しないたびにそれを変換しようとしました。MSSQLからMySQLへの文字列の変換

SQL照合順序はMySQLの照合が(foreachループ内)コードのlatin1_general_ciサンプルですSQL_Latin1_General_CP1_CI_ASでは、以下の通りです:

foreach(var pgObj in PgObjList) 
{ 
    //byte[] bytes = Encoding.Default.GetBytes(pgObj.Description); 
    //pgObj.Description = Encoding.ASCII.GetString(bytes); 

    byte[] utf8Bytes = Encoding.UTF8.GetBytes(pgObj.Description); 
    byte[] isoBytes = Encoding.Convert(Encoding.ASCII, Encoding.UTF8, utf8Bytes); 
    string uf8converted = Encoding.UTF8.GetString(isoBytes); 

    string insertSQL = @"INSERT INTO `mainsite`.`sf_root_items` 
         (`ID`, 
         `LoweredName`, 
         `MenuName`, 
         `Title`, 
         `Description`, 
         `PageType`, 
         `ExternalUrl` 
         ) 
         VALUES 
         ('" + pgObj.ID + @"', 
         '" + pgObj.LoweredName + @"', 
         '" + pgObj.MenuName + @"', 
         '" + pgObj.Title + @"', 
         '" + pgObj.Description + @"', 
         '" + pgObj.PageType + @"', 
         '" + pgObj.ExternalUrl + @"' 
         );"; 
    string outputMsg; 
    // more code here to execute the MySQL statement 
} 

私はASCIIに変換してしまった最良の結果(コメントコード)とそれは漢字のように見えるものの中にテキストを保存しました。例外はありませんでしたが、他の方法で実行した場合、このレコードで例外が発生します。

例外:

MySQL Exception on record#28/r/n 
MySql.Data.MySqlClient.MySqlException (0x80004005): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'il vous plaît (RSVP)', 
               '0', 
      ' at line 15 
     at MySql.Data.MySqlClient.MySqlStream.ReadPacket() 
     at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId) 
     at MySql.Data.MySqlClient.Driver.GetResult(Int32 statementId, Int32& affectedRows, Int64& insertedId) 
     at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force) 
     at MySql.Data.MySqlClient.MySqlDataReader.NextResult() 
     at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) 
     at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery() 
     at SharepointImportDL.SharepointContentImport.GetSitefinityContent.addRootItems(List`1 PgObjList, String WPConnectionString) in C:\Users\Administrator\Source\Repos\TestBinaryWriter\Test Binary Writer\SharepointImportDL\SharepointContentImport\GetSitefinityContent.cs:line 986 

ライン986 SQLの実行です:int output = cmd.ExecuteNonQuery();

また、私が挿入していた文字列がNVARCHARカラム(MSSQL)からのものであることは注目に値するとすることができ、 VARCHAR(MySQLの)列

皮肉なことに、文字列は単純です「Répondezs'il vousのひだ(RSVP)」(私は目を使用していたうぬぼれた人をパンチしたいですeフランス語のテキスト)私は再びそれに遭遇する可能性は低いですが、明らかにこの可能性に対処する必要があります。

+0

UTF-8は、ASCII文字以内のはるかに広い範囲をカバーしています。おそらく、送信する前にUTF-8に変換しておき、保存する前にターゲットデータベースが望む文字コードに変換し直してください。 – rossum

+1

常にパラメータ化されたクエリを使用する必要があります。シンプルなデータ移行ではSQLインジェクションのリスクが低いことはわかっていますが、エスケープとすべてのことにはうまく対応しています。そして、安全な側にいる方が良いです。それはあなたの問題を解決するかもしれません。 –

+0

@rossumは私の無知を許していますが、私はいつ変換するのですか?あなたは "送信前"を提案していますので、これは私のMSSQL select文にありますか?私はこれが私の最初のアプローチだったので、これを行う方法を見ていません – Daniel

答えて

0

SQL(string insertSQL)をビルドする前に、エスケープ文字列(たとえば、pgObj.Description)。そうしないと、単一引用符の内側に単一引用符があるか

, 'Répondez s'il vous plaît (RSVP)', 

お知らせのようなものから、構文エラーを取得しますか?また、エラーが問題で指摘どのように気づく:パラメータ化クエリを示唆ためPalleに起因して

... syntax to use near 'il vous plaît (RSVP)', 
0

おかげで、私はこれらの問題を処理するために、MySQLではストアドプロシージャを書くことにしました。私の元の質問に基づいて

私のC#のコードは、以下の通りです:

foreach(var pgObj in PgObjList) 
{ 
    string SP = "sp_insert_root_items"; 
    string outputMsg = ""; 

    MySqlConnection myConnection = new MySqlConnection(WPConnectionString); 
    MySqlCommand cmd; 
    try 
    { 
     if (myConnection.State != ConnectionState.Open) 
     { 
      myConnection.Close(); 
      myConnection.Open(); 
     } 
     cmd = myConnection.CreateCommand(); 
     cmd.CommandText = SP; 
     cmd.CommandType = CommandType.StoredProcedure; 

     cmd.Parameters.AddWithValue("@ID", pgObj.ID); 
     cmd.Parameters["@ID"].Direction = ParameterDirection.Input; 

     cmd.Parameters.AddWithValue("@LoweredName", pgObj.LoweredName); 
     cmd.Parameters["@LoweredName"].Direction = ParameterDirection.Input; 

     cmd.Parameters.AddWithValue("@MenuName", pgObj.MenuName); 
     cmd.Parameters["@MenuName"].Direction = ParameterDirection.Input; 

     cmd.Parameters.AddWithValue("@Title", pgObj.Title); 
     cmd.Parameters["@Title"].Direction = ParameterDirection.Input; 

     cmd.Parameters.AddWithValue("@Description", pgObj.Description); 
     cmd.Parameters["@Description"].Direction = ParameterDirection.Input; 

     cmd.Parameters.AddWithValue("@PageType", pgObj.PageType); 
     cmd.Parameters["@PageType"].Direction = ParameterDirection.Input; 

     cmd.Parameters.AddWithValue("@ExternalUrl", pgObj.ExternalUrl); 
     cmd.Parameters["@ExternalUrl"].Direction = ParameterDirection.Input; 

     cmd.Parameters.AddWithValue("@ParentID", ""); 
     cmd.Parameters["@ParentID"].Direction = ParameterDirection.Input; 

     int output = cmd.ExecuteNonQuery(); 

     // a value greater than 0 means execution was successful 
     if (output > 0) 
     { 
      counter++; 
      //outputMsg = "Record #" + counter.ToString() + " created"; 

     } 
     else 
     { 
      counter++; 
      outputMsg = "There was an error inserting record #" + counter.ToString(); 
     } 

     myConnection.Close(); 
    } 
    catch (Exception ex) 
    { 
     outputMsg = "MySQL Exception on record#" + counter.ToString() + "/r/n" + ex.ToString(); 
    } 

    returnMsg += outputMsg; 

} 

ストアドプロシージャの例は以下の通りです - それはSQLyogのから輸出されました。

DELIMITER $$ 

/*!50003 CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_insert_root_items`(
     IN ID VARCHAR(255), 
     IN LoweredName VARCHAR(255), 
     IN MenuName VARCHAR(255), 
     IN Title VARCHAR(255), 
     IN Description VARCHAR(500), 
     IN PageType VARCHAR(255), 
     IN ExternalUrl VARCHAR(255), 
     IN ParentID VARCHAR(255) 
    ) 
BEGIN 
    INSERT INTO `wp_sf_page_items` 
     (`ID`, 
     `LoweredName`, 
     `MenuName`, 
     `Title`, 
     `Description`, 
     `PageType`, 
     `ExternalUrl`, 
     `ParentID` 
    ) 
    VALUES(ID, LoweredName, MenuName, Title, Description, PageType, ExternalUrl, ParentID); 
END */$$ 
DELIMITER ; 
関連する問題