【问题标题】:MySQL - Table trigger prevents insert into table and returns no errors?MySQL - 表触发器防止插入表并且不返回错误?
【发布时间】:2016-05-22 17:00:55
【问题描述】:

我正在编写我的第一个触发器一个 MySQL 数据库。触发器的想法是防止任何人插入带有measurement_date 的数据,该数据属于表中已存在的日期范围。换句话说,对于表中的任何给定源,我只希望插入日期晚于最后一个measurement_date 的数据。

创建触发器后,我正在插入数据库的 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.

此触发器的目的是防止任何人插入数据库中已存在测量日期的数据。换句话说,我想防止插入重复值或日期落入此源已存在的日期范围内的值。

为什么我的插入会使应用程序挂起?我的触发器有问题吗。

【问题讨论】:

    标签: c# mysql sql triggers


    【解决方案1】:

    如果发送的值无效,则它会失败,然后重试,因此它会让您在重试前暂停时等待。除了使用触发器之外,您还可以在代码中进行检查,例如将您要输入的值与表中的最大日期进行比较,这将产生相同的结果但没有任何超时,您还可以修改需要的表 id。

    【讨论】:

    • 是的,我认为这种方法。我相信在 MySQL 服务器数据库上执行此操作会比在 C# 代码中快得多。我试图创建某种类型的触发器来过滤插入的值,以尝试删除任何重复的日期值并仅插入新日期。
    • 许多人认为使用触发器来实现业务逻辑(这就是您正在做的事情)是“设计失败”。我知道您使用的是 MySQL 而不是 oracle,但设计原则是正确的。谷歌“tom kyte 触发器问题”以获得详尽的解释。
    • 很棒的文章,我也觉得触发器是自切片面包以来最酷的东西。这篇文章解释了为什么人们不应该将它们用于所有事情。谢谢你,我想我会为我的问题走代码路线。谢谢!
    猜你喜欢
    • 2010-09-05
    • 2020-08-29
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多