我在C中编写了一个处理引擎,它从表中提取40k条记录,处理数据并将结果写入不同的表。当我将处理过的数据打印到屏幕上时,它看起来很完美,因此所有变量都保持正确的值。我需要将数据写入一个有3列作为主键的表。我像这样创建表:
CREATE TABLE halfcomp
(
MarketCode varchar(20) NOT NULL,
TRZNum varchar(20) NOT NULL,
origTRZNum varchar(20) NOT NULL,
PRIMARY KEY (MarketCode, TRZNum, origTRZNum)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
当C程序写入数据库时,我得到的结果是垃圾。我得到重复的值,我不应该,结果是乱序,列看起来切换到位等等。我一直在玩这个几天,我认为它与主键有关。
我认为这是因为我使用自动递增的整数主键创建了另一个表,它将我的其他值释放为普通的旧表值。我创建了这样的表:
CREATE TABLE halfcomp
(
Ind int(11) auto_increment NOT NULL,
MarketCode varchar(20) DEFAULT NULL,
TRZNum varchar(20) DEFAULT NULL,
origTRZNum varchar(20) DEFAULT NULL,
PRIMARY KEY (Ind)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
当我使用相同的C代码写入此表时,结果非常完美。没有重复值,没有混合列。但事情就是这样,我需要MarketCode,TRZNum和origTRZNum列作为主键。我不恰当地创建了我的第一张桌子吗?我很茫然。
我已经使用细齿梳在C程序上,它看起来正确,并且相同的C代码适用于其他表。但是使用这个表,它不起作用。任何见解都将非常感激!谢谢!
编辑:我已更新代码。我不再使用malloc任意或sprintf,我将缓冲区值直接设置为我的字符串变量的值。我也尝试在字符串末尾添加“\ 0”。到目前为止,没有任何帮助,我得到了同样的不稳定行为。仅当值为主键时才会发生这种情况,否则会正确加载。我必须假设C在开始时将数据库信息传递给我时在字符串末尾添加一个空终止符,并且我在处理数据时使用strcpy来回传递值,所以我必须相信null终止符已经存在。还有其他想法吗?
int writeDB(void) {
MYSQL *conn2;
MYSQL_STMT *stmt2;
MYSQL_BIND bind2[3];
char *server = "localhost";
char *user = "root";
char *password = "";
char *database = "thekeydb";
int port = 3306;
int k;
int length = 15000;
unsigned long mc2_length, mn2_length, om2_length;
const char *insertStmt2 = "INSERT INTO tempcomp (MarketCode, TRZNum, origTRZNum) VALUES (?,?,?)";
conn2 = mysql_init(NULL);
mysql_real_connect(conn2, server,user,password,database, port, NULL, 0);
stmt2 = mysql_stmt_init(conn2);
mysql_autocommit(conn2, 0);
mysql_query(conn2, "START TRANSACTION");
for (k=0; k < length; k++) {
memset((void *) bind2, 0, sizeof(bind2));
mc2_length = strlen(comps[k].marketCode);
mn2_length = strlen(comps[k].trzNum);
om2_length = strlen(comps[k].origTrzNum);
if (mysql_stmt_prepare(stmt2, insertStmt2, strlen(insertStmt2)) != 0) {
printf("Unable to create new session: Could not prepare statement\n");
}
bind2[0].buffer_type = MYSQL_TYPE_STRING;
bind2[0].buffer = comps[k].marketCode;
bind2[0].buffer_length = STRING_SIZE;
bind2[0].is_null = 0;
bind2[0].length = &mc2_length;
bind2[1].buffer_type = MYSQL_TYPE_STRING;
bind2[1].buffer = comps[k].trzNum;
bind2[1].buffer_length = STRING_SIZE;
bind2[1].is_null = 0;
bind2[1].length = &mn2_length;
bind2[2].buffer_type = MYSQL_TYPE_STRING;
bind2[2].buffer = comps[k].origTrzNum;
bind2[2].buffer_length = STRING_SIZE;
bind2[2].is_null = 0;
bind2[2].length = &om2_length;
if (mysql_stmt_bind_param(stmt2, bind2) != 0) {
printf("Unable to create new session: Could not bind parameters");
}
mysql_stmt_execute(stmt2);
printf("%s, %s, %s, %s\n", comps[k].marketCode, comps[k].trzNum, comps[k].origTrzNum, comps[k].address);
}
mysql_query(conn2, "COMMIT");
mysql_autocommit(conn2, 1);
mysql_stmt_free_result(stmt2);
mysql_stmt_close(stmt2);
mysql_close(conn2);
return 1;
}
答案 0 :(得分:0)
几乎可以肯定,你不是val cx = new StringField("blockId", "CX")
val seg = StringField("segmentation", "ABC")
val ver = NumberField("version", "1.0")
val myBlock = Block(cx, Seq(seg, ver))
终止你的字符串。如果将字符串作为参数传递给 libmysqlclient 中的预准备语句,则必须指定字符串的长度。如果您的字符串未null
终止并且您使用null
将长度传递给strlen()
结构,或者您 1 将它们传递给{{1}或者类似于构建查询,然后会出现类似于你的porgram行为的意外行为。
1 如果您真的这样做,请不要这样做,而是使用预备语句。
答案 1 :(得分:0)
为了社区,我必须诚实地回答这个问题,不过我承认我很尴尬。此时,我相信我一直在正确地将数据写入数据库,但是错误地查看数据库数据以进行比较。当我将数据打印到屏幕上时,我正在查看三列。第一个是完全重复的市场代码,第二个是相当随机的代码,第三个代码是以5或8组或其他方式重复的代码。当我做一个“SELECT * FROM tempcomp”来查看数据时,它是第二列会重复,但是在较小的组中,如2或3,第三列看起来是随机的。我现在相信MySQL Workbench在将数据呈现给我之前就以某种方式对数据进行排序。因此,数据库显示与程序显示的不同。当我使用auto_incrementing整数作为主键时,数据库以与屏幕显示相同的顺序显示数据。但是当我的三列是主键时,它对输出进行了不同的排序。尝试解决这个问题已经过了3天,并且发现我的代码实际上没有任何错误,至少可以说是尴尬。