对单独的 DATE 和 TIME 使用相同的缓冲区

Use the same buffer for separate DATE and TIME

我正在使用 MySQL C api 以及准备好的语句。发出带有 TIME 字段的 INSERT 查询时,结果采用 HHH:MM:SS 格式,其中小时数是本月经过的小时数。例如,如果日期是 2015-02-21,时间是 21:30:00,则时间将显示为 525:30:00,但我想改用 HH:MM:SS 格式(例如 21:30:00),这将是一天中的实际时间。

sbind[3].buffer_type=MYSQL_TYPE_DATE;
sbind[3].buffer= (char *)&ts; // Pointer to a MYSQL_TIME data structure
sbind[3].is_null= 0;
sbind[3].length= 0;

sbind[4] = sbind[3];
sbind[4].buffer_type=MYSQL_TYPE_TIME;

mysql_stmt_bind_param(stmt, sbind); // sbind is an array of MYSQL_BIND structures

ts.year= 1900+tm_info->tm_year; // tm_info is a pointer to a tm structure
ts.month= 1+tm_info->tm_mon;
ts.day= tm_info->tm_mday;

ts.hour= tm_info->tm_hour;
ts.minute= tm_info->tm_min;
ts.second= tm_info->tm_sec;

此代码会将日期字段准备为 yyyy-mm-dd 并用 tm_info 中的日期填充它。同样,它会对时间字段做同样的事情,但采用 HHH:MM:SS 格式。

当时一种不流行的方法是使用单独的 MYSQL_TIME 结构,但我的目标是采用更优雅的方式来处理这个问题。

(编辑: 这里我包含了相关的客户端代码

MYSQL_TIME  ts;
MYSQL_STMT *stmt;
MYSQL_BIND sbind[2];

...

char query[QUERY_BUFFER_SIZE];
strcpy(query, "INSERT INTO `mytable` (date,time) VALUES(?,?)");
if(mysql_stmt_prepare(stmt, query, strlen(query))){
    return mysql_stmt_errno(stmt);
}

...

time_t rawtime;
time(&rawtime); // get current time
struct tm *tm_info = localtime ( &rawtime );

...

memset(sbind,0,sizeof(sbind));

sbind[0].buffer_type=MYSQL_TYPE_DATE;
sbind[0].buffer= (char *)&ts; // Pointer to a MYSQL_TIME data structure
sbind[0].is_null= 0;
sbind[0].length= 0;

sbind[1] = sbind[0];
sbind[1].buffer_type=MYSQL_TYPE_TIME;

mysql_stmt_bind_param(stmt, sbind); // sbind is an array of MYSQL_BIND structures

ts.year= 1900+tm_info->tm_year; // tm_info is a pointer to a tm structure
ts.month= 1+tm_info->tm_mon;
ts.day= tm_info->tm_mday;

ts.hour= tm_info->tm_hour;
ts.minute= tm_info->tm_min;
ts.second= tm_info->tm_sec;

if(mysql_stmt_execute(stmt)){
    return mysql_stmt_errno(stmt);
}

这假定 mysql 是一个有效的连接。本例中的 table mytable 只包含一个 DATE 类型和一个 TIME 类型。

)

这是 TIME type 的自然表示 - 顾名思义,它只保存时间,这是表示 time 大于 a 的自然方式日。正如文档所建议的那样,它确实对较小的值使用 HH:MM:SS

因为 TIME does not care about shenanigans like leap seconds,要排除全天,只需要 tm_hour%24。但是,为了允许像 DST 转换这样的恶作剧,您只需将 TIME 添加到特定月份的起点并使用股票函数进行 DATETIME 算术。

@:

试图超越 libmysql 失败(mysql-connector-c-6.1.5/libmysql/libmysql.c:1964):

static void store_param_date(NET *net, MYSQL_BIND *param)
{
  MYSQL_TIME tm= *((MYSQL_TIME *) param->buffer);
  tm.hour= tm.minute= tm.second= tm.second_part= 0;
  net_store_datetime(net, &tm);
}

如您所见,它总是用完整个结构(显然,以便相关功能始终按预期工作)。