2016-05-22 24 views
0

我正在寫我的第一個觸發器的MySQL數據庫。觸發器的想法是防止任何人通過measurement_date插入數據,該數據屬於表中已存在的日期範圍。換句話說,我只希望插入的數據對於表中任何給定的來源具有比最後的measurement_date更長的日期。MySQL - 表觸發器防止插入表並返回沒有錯誤?

創建觸發器之後,插入數據庫的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. 

此觸發器的目標是防止任何人插入數據庫中已存在的測量日期。換句話說,我想阻止插入重複值的OR值與日期落入此源已存在的日期範圍。

爲什麼我的插件使應用程序掛起?我的觸發器有故障。

回答

0

如果發送的值無效,則表示失敗,然後重試,因此在重試之前它會暫停等待。您可以在代碼中進行檢查,比如將要輸入的值與表中的最大日期進行比較,以產生相同的結果但沒有任何超時,並且還可以修改表id所需的值。

+0

是的,我雖然關於這種做法。我深信,在MySQL服務器數據庫而不是C#代碼上執行該操作要快得多。我試圖創建某種類型的觸發器來過濾插入的值,以嘗試刪除任何重複的日期值並僅插入新的日期。 –

+1

許多人認爲使用觸發器來實現業務邏輯(這就是你正在做的)是'設計失敗'。我知道你在使用MySQL而不是Oracle,但是設計原則是成立的。谷歌'湯姆吉特與觸發器的麻煩'作了徹底的解釋。 – EdStevens

+0

偉大的文章,我也受到觸發是自切片面包以來最酷的事情的印象。文章解釋了爲什麼不應該把它們用於一切。感謝這個,我想我會走我的問題的代碼路線。謝謝! –