MySQL 存储过程的“第 1 行 'in_operation' 列的数据被截断”问题

'Data truncated for column 'in_operation' at row 1' issue with MySQL stored procedure

我一直在努力解决一些 MySQL 存储过程的奇怪问题。

定义如下:

CREATE DEFINER=`root`@`localhost` PROCEDURE `search_audit`(
IN in_audit_search_type ENUM('USER','IP','HOSTNAME', 'SHARE', 'OPERATION', 'SOURCE', 'DESTINATION', 'ALL'),
IN in_user_name VARCHAR(32),
IN in_client_ip VARCHAR(15),
IN in_host_name VARCHAR(32),
IN in_share_name VARCHAR(32),
IN in_operation VARCHAR(24),
IN in_affected_item VARCHAR(8192),
IN in_new_name VARCHAR(8192),
IN in_start_date DATETIME,
IN in_end_date DATETIME)
BEGIN

    CASE in_audit_search_type
    
        WHEN 'USER'
        THEN
            SELECT
                log_time,
                user_name,
                client_ip,
                host_name,
                share_name,
                operation,
                affected_item,
                new_name
            FROM
                audit
            WHERE
                user_name = in_user_name AND
                log_time BETWEEN in_start_date AND in_end_date;

        WHEN 'IP'
        THEN
            SELECT
                log_time,
                user_name,
                client_ip,
                host_name,
                share_name,
                operation,
                affected_item,
                new_name
            FROM
                audit
            WHERE
                client_ip = in_client_ip AND
                log_time BETWEEN in_start_date AND in_end_date;

        WHEN 'HOSTNAME'
        THEN
            SELECT
                log_time,
                user_name,
                client_ip,
                host_name,
                share_name,
                operation,
                affected_item,
                new_name
            FROM
                audit
            WHERE
                host_name = in_host_name AND
                log_time BETWEEN in_start_date AND in_end_date;

        WHEN 'SHARE'
        THEN
            SELECT
                log_time,
                user_name,
                client_ip,
                host_name,
                share_name,
                operation,
                affected_item,
                new_name
            FROM
                audit
            WHERE
                share_name = in_share_name AND
                log_time BETWEEN in_start_date AND in_end_date;

        WHEN 'OPERATION'
        THEN
            SELECT
                log_time,
                user_name,
                client_ip,
                host_name,
                share_name,
                operation,
                affected_item,
                new_name
            FROM
                audit
            WHERE
                operation = in_operation AND
                log_time BETWEEN in_start_date AND in_end_date;

        WHEN 'SOURCE'
        THEN
            SELECT
                log_time,
                user_name,
                client_ip,
                host_name,
                share_name,
                operation,
                affected_item,
                new_name
            FROM
                audit
            WHERE
                affected_item = in_affected_item AND
                log_time BETWEEN in_start_date AND in_end_date;

        WHEN 'TARGET'
        THEN
            SELECT
                log_time,
                user_name,
                client_ip,
                host_name,
                share_name,
                operation,
                affected_item,
                new_name
            FROM
                audit
            WHERE
                new_name = in_target AND
                log_time BETWEEN in_start_date AND in_end_date;

        ELSE
            SELECT
                log_time,
                user_name,
                client_ip,
                host_name,
                share_name,
                `operation`,
                affected_item,
                new_name
            FROM
                audit
            WHERE
                log_time BETWEEN in_start_date AND in_end_date;   

    END CASE;

END

我正在尝试从我一直在尝试编写的某个 C# 应用程序中调用此存储过程。这是 C# 存储过程对象的定义:

            SEARCH_AUDIT_COMMAND = new MySqlCommand();
        SEARCH_AUDIT_COMMAND.CommandType = System.Data.CommandType.StoredProcedure;
        SEARCH_AUDIT_COMMAND.Connection = DB_CONNECTION;
        SEARCH_AUDIT_COMMAND.CommandText = "search_audit";
        SEARCH_AUDIT_COMMAND.CommandTimeout = 300;
        SEARCH_AUDIT_COMMAND.Parameters.Add("@in_audit_search_type", MySqlDbType.Enum);
        SEARCH_AUDIT_COMMAND.Parameters.Add("@in_user_name", MySqlDbType.VarChar);
        SEARCH_AUDIT_COMMAND.Parameters.Add("@in_client_ip", MySqlDbType.VarChar);
        SEARCH_AUDIT_COMMAND.Parameters.Add("@in_host_name", MySqlDbType.VarChar);
        SEARCH_AUDIT_COMMAND.Parameters.Add("@in_share_name", MySqlDbType.VarChar);
        SEARCH_AUDIT_COMMAND.Parameters.Add("@in_operation", MySqlDbType.VarChar);
        SEARCH_AUDIT_COMMAND.Parameters.Add("@in_affected_item", MySqlDbType.VarChar);
        SEARCH_AUDIT_COMMAND.Parameters.Add("@in_new_name", MySqlDbType.VarChar);
        SEARCH_AUDIT_COMMAND.Parameters.Add("@in_start_date", MySqlDbType.DateTime);
        SEARCH_AUDIT_COMMAND.Parameters.Add("@in_end_date", MySqlDbType.DateTime);

这是我检索记录的方法:

        internal BindingList<AuditRecord> SearchAuditRecords(
        AuditSearchType searchType,
        string inUserName,
        string inClientIP,
        string inHostName,
        string inShareName,
        string inOperation,
        string inAffectedItem,
        string inNewName,
        DateTime startDate,
        DateTime endDate)
    {

        SEARCH_AUDIT_COMMAND.Parameters["@in_audit_search_type"].Value = searchType.ToString();
        SEARCH_AUDIT_COMMAND.Parameters["@in_user_name"].Value = inUserName;
        SEARCH_AUDIT_COMMAND.Parameters["@in_client_ip"].Value = inClientIP;
        SEARCH_AUDIT_COMMAND.Parameters["@in_host_name"].Value = inHostName;
        SEARCH_AUDIT_COMMAND.Parameters["@in_share_name"].Value = inShareName;
        SEARCH_AUDIT_COMMAND.Parameters["@in_operation"].Value = inOperation;
        SEARCH_AUDIT_COMMAND.Parameters["@in_affected_item"].Value = inAffectedItem;
        SEARCH_AUDIT_COMMAND.Parameters["@in_new_name"].Value = inNewName;
        SEARCH_AUDIT_COMMAND.Parameters["@in_start_date"].Value = startDate;
        SEARCH_AUDIT_COMMAND.Parameters["@in_end_date"].Value = endDate;


        DB_CONNECTION.Open();
        MySqlDataReader reader = SEARCH_AUDIT_COMMAND.ExecuteReader();

        BindingList<AuditRecord> records = new BindingList<AuditRecord>();

        while (reader.Read())
        {

            DateTime logDate = reader.GetDateTime(0);
            string userName = reader.GetString(1);
            string clientIP = reader.GetString(2);
            string hostName = reader.GetString(3);
            string shareName = reader.GetString(4);
            string operation = reader.GetString(5);
            string affectedItem = reader.GetString(6);
            string newName = reader.GetString(7);

            AuditRecord temp = new AuditRecord(logDate,userName, clientIP, hostName, shareName, operation, affectedItem, newName);
            records.Add(temp);
        }

        DB_CONNECTION.Close();

        return records;
    }

当我调用这个方法时,我得到这个异常:

MySql.Data.MySqlClient.MySqlException: 'Data truncated for column 'in_operation' at row 1'

但是如果我删除这一行,它会起作用:

SEARCH_AUDIT_COMMAND.Parameters["@in_operation"].Value = inOperation;

如果我像这样编辑该行,它也有效:

SEARCH_AUDIT_COMMAND.Parameters["@in_operation"].Value = null;

这是“审计”table创建语句:

    CREATE TABLE `audit` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `log_time` datetime DEFAULT NULL,
  `user_name` varchar(32) DEFAULT NULL,
  `client_ip` varchar(15) DEFAULT NULL,
  `host_name` varchar(32) DEFAULT NULL,
  `share_name` varchar(32) DEFAULT NULL,
  `operation` varchar(32) DEFAULT NULL,
  `affected_item` varchar(8192) DEFAULT NULL,
  `new_name` varchar(8192) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `USER` (`user_name`,`share_name`,`operation`),
  KEY `SHARE` (`share_name`,`user_name`,`operation`),
  KEY `OPERATION` (`operation`,`user_name`,`share_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我一直在绞尽脑汁试图理解为什么会抛出异常。我已经在互联网上搜索了答案。我现在正在考虑自杀。

发生截断是因为在过程中您将 in_operation 声明为 VARCHAR(24),但创建 table 语句中的 operation 列是 VARCHAR(32)。要修复此更改,请将过程声明中的 VARCHAR(24) 替换为 VARCHAR(32)

{...}
IN in_operation VARCHAR(32),
{...}