私は最初のトリガを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値が重複して挿入されないようにしたいのです。
なぜ私の挿入によってアプリケーションがハングアップするのですか?私のトリガーは間違っていますか?
はい、私はこのアプローチについて考えています。私は、これがC#コードではなくMySQLサーバデータベースで行うほうがはるかに高速であると信じていました。重複した日付の値を削除して新しい日付のみを挿入しようとするために挿入された値をフィルターするトリガーを作成しようとしました。 –
多くの人々は、トリガーを使用してビジネスロジック(あなたがやっていること)を実装することを「設計失敗」と考えています。私はあなたがオラクルではなくMySQL上にいることを知っていますが、設計原則は真実です。 Googleが徹底した説明をするために、「トムキーのトライアルによるトラブル」 – EdStevens
偉大な記事、私はトリガーがスライスされたパン以来の最もクールなものであるという印象の下にあった。この記事では、なぜそれらをすべてに使用すべきでないのかを説明しています。ありがとう、私は私の問題のコードルートに行くと思う。ありがとうございました! –