解決Incorrect datetime value: '' for column 'time' at row 1的問題
阿新 • • 發佈:2019-01-29
環境說明:
作業系統:REHL 6.3
開發語言:C
第二次:
第三次:
由上可以比較發現兩處特別差異:
ts是MYSQL_TIME型別的結構體變數,其成員second_part和time_type在三次比較中,第一次異於後兩次。因此大膽的假設在此情況ts變數的second_part和time_type的值分別為0和MYSQL_TIMESTAMP_DATE。咱在如下程式碼之後:
新增如下兩句:
正常執行,發覺問題解決了。good!
對於列舉enum_mysql_timestamp_type型別:
其中可以發現列舉型別對於特定的時間欄位DATE、DATETIME、TIMESTAMP有一一對應的值:
以後切記在使用MYSQL_TIME結構體的時候,如果出錯,及時的對每一個成員賦相應的值。。。。
Over,好睏啊!該午睡了!!!!!!
作業系統:REHL 6.3
開發語言:C
資料庫:Mysql 5.6
病症:
最近做linux 下資料庫儲存的開發,對於一張資料庫表中的一個DATETIME欄位進行插入操作,各種儲存變數值設定完成後,進行mysql_stmt_execute()操作,mysql_stmt_error()返回:Incorrect datetime value: '' for column 'time' at row 1。錯誤資訊是指time欄位的datetime 值不正確,而且此錯誤僅出現在進行第一次插入的時候,第二次、第三次以及以後的都正常。進行插入操作我是通過C API的預處理語句來執行的。程式碼如下:
int insert_enydata(MYSQL *mysql, q_socketinfo *p_sock, q_enydata *p) { if(mysql == NULL || p == NULL) return -1; char insql[] = "insert into q_enydata(srcip, srcport, dstip, dstport, qid, qqver, seqno, ncmd, ntype, data, time) \ values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; MYSQL_BIND bind[11]; unsigned long length, srclen, dstlen; MYSQL_TIME ts; MYSQL_STMT *stmt = mysql_stmt_init(mysql); char str[] = "0"; if (!stmt) { fprintf(stderr, " mysql_stmt_init(), out of memory\n"); return -1; } if (mysql_stmt_prepare(stmt, insql, strlen(insql))) { fprintf(stderr, "\n mysql_stmt_prepare(), INSERT failed"); goto MYSQL_ERROR; } //sip memset(bind, 0, sizeof(bind)); bind[0].buffer= (char *)(p_sock->sip); bind[0].buffer_type= MYSQL_TYPE_VAR_STRING; bind[0].buffer_length= STRING_SIZE; bind[0].is_null= 0; bind[0].length= &srclen; //sport bind[1].buffer = (char *)&(p_sock->sport); bind[1].buffer_type = MYSQL_TYPE_LONG; bind[1].length= 0; bind[1].is_null= 0; //dip bind[2].buffer = (char *)(p_sock->dip); bind[2].buffer_type = MYSQL_TYPE_VAR_STRING; bind[2].buffer_length = STRING_SIZE; bind[2].length= &dstlen; bind[2].is_null= 0; //dport bind[3].buffer = (char *)&(p_sock->dport); bind[3].buffer_type = MYSQL_TYPE_LONG; bind[3].length= 0; bind[3].is_null= 0; //qid bind[4].buffer = (char *)&(p->qid); bind[4].buffer_type = MYSQL_TYPE_LONG; bind[4].length= 0; bind[4].is_null= 0; //qqver bind[5].buffer = (char *)&(p->qqver); bind[5].buffer_type = MYSQL_TYPE_LONG; bind[5].length= 0; bind[5].is_null= 0; //seqno bind[6].buffer = (char *)&(p->seqno); bind[6].buffer_type = MYSQL_TYPE_LONG; bind[6].length= 0; bind[6].is_null= 0; //ncmd bind[7].buffer = (char *)&(p->ncmd); bind[7].buffer_type = MYSQL_TYPE_LONG; bind[7].length= 0; bind[7].is_null= 0; //ntype bind[8].buffer = (char *)&(p->ntype); bind[8].buffer_type = MYSQL_TYPE_LONG; bind[8].length= 0; bind[8].is_null= 0; //data bind[9].buffer = str; bind[9].buffer_type = MYSQL_TYPE_LONG_BLOB; bind[9].buffer_length = DATA_LEN; bind[9].length= &length; bind[9].is_null= 0; //time bind[10].buffer = (char *)&ts; bind[10].buffer_type = MYSQL_TYPE_DATETIME; bind[10].length= 0; bind[10].is_null= 0; // Bind the buffers if (mysql_stmt_bind_param(stmt, bind)) { fprintf(stderr, "\n param bind failed"); goto MYSQL_ERROR; } // Supply data in chunks to server srclen = strlen((char *)p_sock->sip); dstlen = strlen((char *)p_sock->dip); length = p->len; if (mysql_stmt_send_long_data(stmt, 9, (char *)p->data, length)) { fprintf(stderr, "\n send_long_data failed"); goto MYSQL_ERROR; } time_t tmt = p->time; struct tm *ltime = localtime(&tmt); ts.year = ltime->tm_year+1900; ts.month = ltime->tm_mon+1; ts.day = ltime->tm_mday; ts.hour = ltime->tm_hour; ts.minute = ltime->tm_min; ts.second = ltime->tm_sec; // Execute the query if (mysql_stmt_execute(stmt)) { fprintf(stderr, "\n mysql_stmt_execute failed"); goto MYSQL_ERROR; } mysql_stmt_close(stmt); return get_id(mysql, "select MAX(id) from q_enydata"); MYSQL_ERROR: fprintf(stderr, "\n Stmt error: %s\n Error: %s\n", mysql_stmt_error(stmt), mysql_error(mysql)); mysql_stmt_close(stmt); return -1; }
以上程式碼是返回錯誤前的程式碼。
在資料庫表中,time欄位是DATETIME型別。根據Mysql 對MYSQL_BIND結構的buffer_type成員的定義,表結構中SQL型別是DATETIME對應Buffer_type是MYSQL_TYPE_DATETIME,其C型別是MYSQL_TIME。表明程式碼沒錯,繫結型別也是正確的,所以應該不會出現不正確的DATETIME值。
繼續分析每次進行插入操作時ts和ltime的值進行檢視對比,通過GDB除錯比較第一次(插入失敗)、第二次(插入成功)、第三次(插入成功).......發現如下情況:
第一次:
(gdb) p ts $1 = {year = 2013, month = 6, day = 5, hour = 12, minute = 42, second = 42, second_part = 140737354126944, neg = 48 '0', time_type = 32767} (gdb) p *ltime $2 = {tm_sec = 42, tm_min = 42, tm_hour = 12, tm_mday = 5, tm_mon = 5, tm_year = 113, tm_wday = 3, tm_yday = 155, tm_isdst = 0, tm_gmtoff = 28800, tm_zone = 0x637040 "CST"} (gdb)
第二次:
(gdb) p ts $3 = {year = 2013, month = 6, day = 5, hour = 12, minute = 42, second = 42, second_part = 0, neg = 111 'o', time_type = MYSQL_TIMESTAMP_DATE} (gdb) p *ltime $4 = {tm_sec = 42, tm_min = 42, tm_hour = 12, tm_mday = 5, tm_mon = 5, tm_year = 113, tm_wday = 3, tm_yday = 155, tm_isdst = 0, tm_gmtoff = 28800, tm_zone = 0x637040 "CST"} (gdb)
第三次:
(gdb) p ts
$5 = {year = 2013, month = 6, day = 5, hour = 12, minute = 42, second = 42,
second_part = 0, neg = 0 '\000', time_type = MYSQL_TIMESTAMP_DATE}
(gdb) p *ltime
$6 = {tm_sec = 42, tm_min = 42, tm_hour = 12, tm_mday = 5, tm_mon = 5,
tm_year = 113, tm_wday = 3, tm_yday = 155, tm_isdst = 0, tm_gmtoff = 28800,
tm_zone = 0x637040 "CST"}
(gdb)
由上可以比較發現兩處特別差異:
ts是MYSQL_TIME型別的結構體變數,其成員second_part和time_type在三次比較中,第一次異於後兩次。因此大膽的假設在此情況ts變數的second_part和time_type的值分別為0和MYSQL_TIMESTAMP_DATE。咱在如下程式碼之後:
time_t tmt = p->time;
struct tm *ltime = localtime(&tmt);
ts.year = ltime->tm_year+1900;
ts.month = ltime->tm_mon+1;
ts.day = ltime->tm_mday;
ts.hour = ltime->tm_hour;
ts.minute = ltime->tm_min;
ts.second = ltime->tm_sec;
新增如下兩句:
ts.second_part = 0;
ts.time_type = MYSQL_TIMESTAMP_DATE;
正常執行,發覺問題解決了。good!
延伸:
在mysql_time.h中,對於MYSQL_TIME結構體:
typedef struct st_mysql_time
{
unsigned int year, month, day, hour, minute, second;
unsigned long second_part; /**< microseconds */
my_bool neg;
enum enum_mysql_timestamp_type time_type;
} MYSQL_TIME;
對於列舉enum_mysql_timestamp_type型別:
enum enum_mysql_timestamp_type
{
MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1,
MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2
};
其中可以發現列舉型別對於特定的時間欄位DATE、DATETIME、TIMESTAMP有一一對應的值:
MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2
以後切記在使用MYSQL_TIME結構體的時候,如果出錯,及時的對每一個成員賦相應的值。。。。
Over,好睏啊!該午睡了!!!!!!