2016-05-22 4 views
0

私は最初のトリガをMySQL DBで作成しています。トリガーの考え方は、テーブルに既に存在する日付の鳴動に該当するmeasurement_dateのデータが誰にも挿入されないようにすることです。言い換えれば、私はテーブル内の任意のソースの最後のmeasurement_dateよりも遅い日付のデータを挿入したいだけです。MySQL - テーブルトリガーはテーブルへの挿入を防ぎ、エラーを返しません?

トリガを作成した後、dbに挿入していたC#アプリケーションがハングアップしてから、挿入を実行すると最終的にタイムアウトします。私がトリガーとに挿入していますテーブルの構造は次のとおりです。これが私のトリガーである

EXPLAIN mydb.water_data; 
_______________________________________________________________ 
|Field   |Type   |Null |Key |Extra   | 
---------------------------------------------------------------- 
|dataID   |int(11)  |NO  |PRI |auto_increment | 
|cond   |int(11)  |YES |  |    | 
|temp   |int(11)  |YES |  |    | 
|measurment_date |datetime  |YES |  |    | 
|sourceid  |varchar(255) |YES |MUL |    | 

DELIMITER // 
CREATE TRIGGER 
    before_insert_waterdata 
BEFORE INSERT ON 
    mydb.water_data 
FOR EACH ROW 
BEGIN 
DECLARE last_date DATETIME; 
DECLARE message VARCHAR(225);  

SELECT WD.measurment_date 
INTO last_date 
FROM mydb.water_data WD 
WHERE WD.sourcbefore_insert_waterdataeID = NEW.measurment_date; 

IF (NEW.measurment_date <= last_date) 
THEN 
    SET message = "ERROR: Dataset that is being inserted includes a date range that is already present in the database. Insert aborted."; 
    SIGNAL SQLSTATE '45000' SET message_text = message; 
END IF; 

END;// 

私のC#アプリケーションからのコードは以下の通りです:

using (MySqlConnection connection = new MySqlConnection(ConnectionString)) 
     { 
      try 
      { 
       connection.Open(); 
       List<string> Rows = new List<string>(); 

       foreach (var chunk in splitData) 
       { 
        StringBuilder sCommand = new StringBuilder("INSERT INTO water_data (cond, temp, measurment_date, sourceid) VALUES "); 
        foreach (var date in chunk) 
        { 
         Rows.Add(string.Format("({0}, {1}, '{2}', '{3}')", MySqlHelper.EscapeString(date.cond.ToString()), MySqlHelper.EscapeString("NULL"), MySqlHelper.EscapeString(date.measurment_date.GetValueOrDefault().ToString("yyyy-MM-dd HH':'mm':'ss", System.Globalization.CultureInfo.InvariantCulture)), MySqlHelper.EscapeString(date.sourceid))); 
        } 
        sCommand.Append(string.Join(",", Rows)); 
        sCommand.Append(";"); 

        using (MySqlCommand myCmd = new MySqlCommand(sCommand.ToString(), connection)) 
        { 
         myCmd.CommandType = CommandType.Text; 
         myCmd.ExecuteNonQuery(); // <------------ The App Crashes right here!!! 
        } 
       } 
       connection.Close(); 
      } 
      catch(MySqlException ex) 
      { 
       Debugger.Break(); 
       ApplicationLog.WriteMessageToLog("ERROR: In Uploader(), There was an error connecting to the database, please check that your connection settings are valid.\n" + ex.Message, true, true, true); 
      } 

最後に、タイムアウトエラーが発生します。

Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. 

このトリガーの目的は、DBにすでに存在する測定日のデータを誰も挿入しないようにすることです。言い換えれば、このソースの既存の日付範囲に該当する日付のOR値が重複して挿入されないようにしたいのです。

なぜ私の挿入によってアプリケーションがハングアップするのですか?私のトリガーは間違っていますか?

答えて

0

送信された値が無効な場合、失敗してから再試行しているため、再試行する前に一時停止中に待機しています。トリガを使用する代わりに、入力したい値とテーブルからの最大日付を比較して同じ結果が得られますが、タイムアウトが発生しないようにチェックすることができます。また、必要なテーブルIDを修正することもできます。

+0

はい、私はこのアプローチについて考えています。私は、これがC#コードではなくMySQLサーバデータベースで行うほうがはるかに高速であると信じていました。重複した日付の値を削除して新しい日付のみを挿入しようとするために挿入された値をフィルターするトリガーを作成しようとしました。 –

+1

多くの人々は、トリガーを使用してビジネスロジック(あなたがやっていること)を実装することを「設計失敗」と考えています。私はあなたがオラクルではなくMySQL上にいることを知っていますが、設計原則は真実です。 Googleが徹底した説明をするために、「トムキーのトライアルによるトラブル」 – EdStevens

+0

偉大な記事、私はトリガーがスライスされたパン以来の最もクールなものであるという印象の下にあった。この記事では、なぜそれらをすべてに使用すべきでないのかを説明しています。ありがとう、私は私の問題のコードルートに行くと思う。ありがとうございました! –

関連する問題