初次尝试用C语言操纵MYSQL,还见海量!
上次初步使用C语言访问MYSQL 用C语言去操作MYSQL
这次就用C语言去完成实际功能, 很多的时候系统运行都有业务日志表,这些表的数量非常大,时间长了保留也没啥用,数据库的维护和数据的维护都丢给了DBA! 没办法DBA就是管数据库这事的,DBA职责就是维护数据库的稳定和性能的丝滑!
本来用了SHELL脚本,后来用了MYSQL 存储过程+事件调度器.
这些运维能看得懂,甚至想动手改, 存储过程开发也能看得懂!
用C语言能看得懂的不多吧! 会维护就少了,尤其是指针不好整!
第一 程序目录架构
[deploy@AesygoDB=>DelBigTable]$pwd
/home/deploy/Project/DelBigTable
用户空间, 用户项目目录, 特定删除大表目录,具体项目

include: 头文件
lib: 静态库和动态库
bin:目标程序目录, 可能附带其它的工具
logs:主程序运行日志
conf:主程序配置文件
source:主程序源码目录
test.exe 编译后的主程序
makeC 编译命令集合
第二 编译说明
clear
gcc ./source/main.c -g -std=c11 -I./include -lmysqlclient -L./lib -Wl,-rpath,'lib' -o test.exe
gcc 后面跟着是源码文件
-g 表示带上调试信息
-std=c11 使用C11语法
-I./include 告诉头文件目录
-lmysqlclient 表示使用MYSQLCLIENT动态库
-L./lib 表示从/lib下找动态库
-Wl,-rpath,'lib' 表示运行期间从程序运行当前目录下找 LIB目录下
-o test.exE 输出TEST.EXE
第三配置文件
#PASSWORD SIZE 35
#logfilename size 35
#SQL SIZE 2048-1
IPAD=192.168.0.227
USER=root
PROT=3306
PAWD=Sharkz@AESYGO
SCHM=lts
TOTAL_SQL=SELECT COUNT(*) as ALLROWS FROM lts.lts_job_log_po WHERE gmt_created< UNIX_TIMESTAMP(date_add(now(), interval -30 day)) *1000
LIMIT_ROWS=1000
DEL_SQL=DELETE FROM lts.lts_job_log_po WHERE gmt_created< UNIX_TIMESTAMP(date_add(now(), interval -30 day)) *1000
LOG_FILE_NAME=DelBigTableLog.txt
#号是注解,
下面就是具体参数, 我们这里规定了参数大小写一致,参数名字要一致
这里TOTAL_SQL SQL 没有双引号,没有分号. 长度限制为2048
另外参数要顶格
因为 程序判断 #号,换行符,回车符和 空格都会跳过
第四 主程序解读
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <stdint.h>
#include "../include/mysql/mysql.h"
//C99
typedef char char1;
typedef wchar_t varchar4;
typedef int8_t int1;
typedef int16_t int2;
typedef int32_t int4;
typedef int64_t int8;
typedef uint8_t uint1;
typedef uint16_t uint2;
typedef uint32_t uint4;
typedef uint64_t uint8;
typedef struct
{
char ip[35];
char user[35];
char port[5];
char passwd[35];
char schema[35];
uint2 limit_rows;
char TOTAL_SQL[2049];
char DEL_SQL[2049];
char logfile[35];
} Tparameter;
这的头文件都是有用的,另外还定义了整形方便形式.
还定义了个参数结构体类型.
2 函数说明
int ReadLine( FILE* pFileHandle, char *Keys[],const int KeysLength,Tparameter* pParameter);
int ReadKeyValue( FILE* pFileHandle,int* plast_row, char* pKey, char *pValue);
int GetFileRowNum( FILE* pFileHandle);
int GetTotal();
int ExecuteDel();
第一个函数ReadLine 是一次性访问配置文件,并把参数读到参数结构体里面
char *Keys[], const int KeysLength
这两个参数 是要 主函数 传递对比的参数名数组和长度. 否则怎么判断
第二个函数
ReadKeyValue ( FILE* pFileHandle,int* plast_row, char* pKey, char *pValue);
也是读配置文件,不过这个就比较通用,它只要读到KEY=VALUE就返回给主函数去判断.
目前来说 重复读取CONF才能获取所有的参数,效率不高.
目前只通过上次读取的LAST_ROWS来进行定位,避免多次读取.
应该可以通过读取字节来重新定位,进一步提升效率.
后面两个参数是返回KEY VALUE的指针. 这里是要主函数提供接受标量的地址;
int GetFileRowNum( FILE* pFileHandle); 这个是获得配置文件总行数.
下面两个函数没有实现,另外写日志文件也没有实现.
3 读配置文件 主函数部分
int main(int argc, char const *argv[])
{
Tparameter sParameter;
FILE* fpFileHandle = NULL;
char *pFileName="./conf/DelLogTable.conf"; //文件句柄
char* Keys[9]={"IPAD","USER","PROT","PAWD","SCHM","TOTAL_SQL","LIMIT_ROWS","DEL_SQL","LOG_FILE_NAME"};
int iReadLineStatus;
fpFileHandle = fopen(pFileName,"r"); //打开文件,读取模式,返回文件句柄
/*
if(fpFileHandle !=NULL)
{
fseek(fpFileHandle,0,0); //移动文件句柄到文件头部
iReadLineStatus=ReadLine(fpFileHandle,Keys,9,&sParameter); //调用上面函数
if(iReadLineStatus==0) //读到真实内容就
{
printf("IP:%s\n",sParameter.ip);
printf("USER:%s\n",sParameter.user);
printf("PROT:%s\n",sParameter.port);
printf("PAWD:%s\n",sParameter.passwd);
printf("SCHM:%s\n",sParameter.schema);
printf("TOTAL_SQL:%s\n",sParameter.TOTAL_SQL);
printf("LIMIT_ROWS:%d\n",sParameter.limit_rows);
printf("DEL_SQL:%s\n",sParameter.DEL_SQL);
printf("LOG_FILE_NAME:%s\n",sParameter.logfile);
}
}
*/
if(fpFileHandle !=NULL)
{
int TotalRow =0;
TotalRow = GetFileRowNum(fpFileHandle);
int iReadKeyValue=1,last_row=1;
char key[35];
char value[2049];
for (int i=1 ; i<=TotalRow; i++)
{
iReadKeyValue = ReadKeyValue(fpFileHandle,&last_row,key, value);
if ( iReadKeyValue == 0)
{
for (int f=0; f < 9; f++)
if ( strcmp(key,Keys[f]) == 0)
{
switch(f) // char* Keys[9]={"IPAD","USER","PROT","PAWD","SCHM","TOTAL_SQL","LIMIT_ROWS","DEL_SQL","LOG_FILE_NAME"};
{
case 0 : strcpy(sParameter.ip,value);break;
case 1 : strcpy(sParameter.user,value);break;
case 2 : strcpy(sParameter.port,value);break;
case 3 : strcpy(sParameter.passwd,value);break;
case 4 : strcpy(sParameter.schema,value);break;
case 5 : strcpy(sParameter.TOTAL_SQL,value); break;
case 6 : sParameter.limit_rows=atoi(value); break;
case 7 : strcpy(sParameter.DEL_SQL,value); break;
case 8 : strcpy(sParameter.logfile,value);break;
default: break;
}//witch
break;
}//if
}
}
printf("IP:%s\n",sParameter.ip);
printf("USER:%s\n",sParameter.user);
printf("PROT:%s\n",sParameter.port);
printf("PAWD:%s\n",sParameter.passwd);
printf("SCHM:%s\n",sParameter.schema);
printf("TOTAL_SQL:%s\n",sParameter.TOTAL_SQL);
printf("LIMIT_ROWS:%d\n",sParameter.limit_rows);
printf("DEL_SQL:%s\n",sParameter.DEL_SQL);
printf("LOG_FILE_NAME:%s\n",sParameter.logfile);
}
注解那段函数也是有效的.
开始 定义了 参数变量, 文件句柄变量,文件名和路径,KEY数组
然后文件只读模式打开, 接着就是使用第一个函数读取配置文件
这段注解掉了, 代码比较简单. 判断读成功后就打印参数变量的值
iReadLineStatus=ReadLine(fpFileHandle,Keys,9,&sParameter);
第二段 局部可以定义变量; 先读取配置文件中函数, 然后循环去读取,假设全部
都是参数,也就是13行. 那么就FOR循环13次就OK
我们定义函数返回执行状态变量, 上次读取行数,接受KEY VALUE的变量.
读取到了KEY 还要跟KEY数组里进行对比 这就要来一次FOR 循环for (int f=0; f < 9; f++)然后对比KEY if ( strcmp(key,Keys[f]) == 0)
后面就是SWITCH(F)加载到对应的参数结构体变量中.
接下来就是 MYSQL操纵代码部分,跟上篇差不多!
MYSQL my_connection;
int connect_flag = 0;
mysql_init(&my_connection); //初始化链接
char* pHost;
char* pUser;
char* pPassword;
char* pSchema;
pHost=sParameter.ip;
pUser=sParameter.user;
pPassword=sParameter.passwd;
pSchema = sParameter.schema;
if (mysql_real_connect(&my_connection,pHost,pUser,pPassword,pSchema,atoi(sParameter.port),NULL,CLIENT_FOUND_ROWS))
{
printf("Mysql Connect succent!\n");
connect_flag = 1;
}
else
{
printf("Mysql Connect succent!\n");
connect_flag = 0;
}
if ( connect_flag == 1)
{
MYSQL_RES* res_ptr; //返回结果集指针
MYSQL_ROW result_row; //返回行
int res,row,column; //行列
long affected_rows = 0;
uint8 Count_Rows = 0;
mysql_query(&my_connection,"set names utf8mb4"); //设置字符集
res =mysql_query(&my_connection,sParameter.TOTAL_SQL); //执行查询语句
affected_rows = mysql_affected_rows(&my_connection);
if(res) { printf("Query Faile %s\n",mysql_error(&my_connection)); } //返回错误
else
{
res_ptr = mysql_store_result(&my_connection); //获取这次结果集
if (res_ptr)
{
row=mysql_num_rows(res_ptr); //获取行数
column=mysql_num_fields(res_ptr); //获取列数
MYSQL_FIELD* FIELD_NAME_ARRY=mysql_fetch_fields(res_ptr); //获取列名
for (int c=0; c < column; c++)
{
printf("%s\t",FIELD_NAME_ARRY[c].name);
}
printf("\n");
for(int i=1; i< row+1;i++) //打印行内容
{
result_row= mysql_fetch_row(res_ptr); //提取行到行变量 提取了 MYSQL服务器端就被清空,只能提取一次
for (int j=0; j < column;j++)
{
printf("%s\t",result_row[j]); //从行变量 获取列的VALUE
}
printf("\n");
}
//result_row= mysql_fetch_row(res_ptr); //提取行到行变量
Count_Rows = atoi(result_row[0]);
printf("Count_Rows:%d\n",Count_Rows);
printf("Count_times:%d\n",Count_Rows/sParameter.limit_rows+1);
}
}
int iLoopTimes = Count_Rows/sParameter.limit_rows+1;
strcat(sParameter.DEL_SQL," ");
strcat(sParameter.DEL_SQL,"limit");
strcat(sParameter.DEL_SQL," ");
char sLimitRows[10];
sprintf(sLimitRows,"%d",sParameter.limit_rows);
strcat(sParameter.DEL_SQL,sLimitRows);
for ( int i=0 ; i<iLoopTimes; i++)
{
res =mysql_query(&my_connection,sParameter.DEL_SQL); //执行删除语句
if(res) { printf("Delete Faile %s\n",mysql_error(&my_connection)); }
else
{
affected_rows = mysql_affected_rows(&my_connection);
printf("Affected row:%d\n",affected_rows);
}
}
}
mysql_close(&my_connection);
}
运行结果:
[deploy@AesygoDB=>DelBigTable]$./test.exe
IP:192.168.0.227
USER:root
PROT:3306
PAWD:Sharkz@AESYGO
SCHM:lts
TOTAL_SQL:SELECT COUNT(*) as ALLROWS FROM lts.lts_job_log_po WHERE gmt_created< UNIX_TIMESTAMP(date_add(now(), interval -30 day)) *1000
LIMIT_ROWS:1000
DEL_SQL:DELETE FROM lts.lts_job_log_po WHERE gmt_created< UNIX_TIMESTAMP(date_add(now(), interval -30 day)) *1000
LOG_FILE_NAME:DelBigTableLog.txt
Mysql Connect succent!
ALLROWS
18
Count_Rows:18
Count_times:1
Affected row:18
[deploy@AesygoDB=>DelBigTable]$
下面是全部代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <stdint.h>
#include "../include/mysql/mysql.h"
//C99
typedef char char1;
typedef wchar_t varchar4;
typedef int8_t int1;
typedef int16_t int2;
typedef int32_t int4;
typedef int64_t int8;
typedef uint8_t uint1;
typedef uint16_t uint2;
typedef uint32_t uint4;
typedef uint64_t uint8;
typedef struct
{
char ip[35];
char user[35];
char port[5];
char passwd[35];
char schema[35];
uint2 limit_rows;
char TOTAL_SQL[2049];
char DEL_SQL[2049];
char logfile[35];
} Tparameter;
//---------------------------------------------------------------------------------------------------------------------
int ReadLine( FILE* pFileHandle, char *Keys[],const int KeysLength,Tparameter* pParameter);
int ReadKeyValue( FILE* pFileHandle,int* plast_row, char* pKey, char *pValue);
int GetFileRowNum( FILE* pFileHandle);
int GetTotal();
int ExecuteDel();
//---------------------------------------------------------------------------------------------------------------------
int main(int argc, char const *argv[])
{
Tparameter sParameter;
FILE* fpFileHandle = NULL;
char *pFileName="./conf/DelLogTable.conf"; //文件句柄
char* Keys[9]={"IPAD","USER","PROT","PAWD","SCHM","TOTAL_SQL","LIMIT_ROWS","DEL_SQL","LOG_FILE_NAME"};
int iReadLineStatus;
fpFileHandle = fopen(pFileName,"r"); //打开文件,读取模式,返回文件句柄
/*
if(fpFileHandle !=NULL)
{
fseek(fpFileHandle,0,0); //移动文件句柄到文件头部
iReadLineStatus=ReadLine(fpFileHandle,Keys,9,&sParameter); //调用上面函数
if(iReadLineStatus==0) //读到真实内容就
{
printf("IP:%s\n",sParameter.ip);
printf("USER:%s\n",sParameter.user);
printf("PROT:%s\n",sParameter.port);
printf("PAWD:%s\n",sParameter.passwd);
printf("SCHM:%s\n",sParameter.schema);
printf("TOTAL_SQL:%s\n",sParameter.TOTAL_SQL);
printf("LIMIT_ROWS:%d\n",sParameter.limit_rows);
printf("DEL_SQL:%s\n",sParameter.DEL_SQL);
printf("LOG_FILE_NAME:%s\n",sParameter.logfile);
}
}
*/
if(fpFileHandle !=NULL)
{
int TotalRow =0;
TotalRow = GetFileRowNum(fpFileHandle);
int iReadKeyValue=1,last_row=1;
char key[35];
char value[2049];
for (int i=1 ; i<=TotalRow; i++)
{
iReadKeyValue = ReadKeyValue(fpFileHandle,&last_row,key, value);
if ( iReadKeyValue == 0)
{
for (int f=0; f < 9; f++)
if ( strcmp(key,Keys[f]) == 0)
{
switch(f) // char* Keys[9]={"IPAD","USER","PROT","PAWD","SCHM","TOTAL_SQL","LIMIT_ROWS","DEL_SQL","LOG_FILE_NAME"};
{
case 0 : strcpy(sParameter.ip,value);break;
case 1 : strcpy(sParameter.user,value);break;
case 2 : strcpy(sParameter.port,value);break;
case 3 : strcpy(sParameter.passwd,value);break;
case 4 : strcpy(sParameter.schema,value);break;
case 5 : strcpy(sParameter.TOTAL_SQL,value); break;
case 6 : sParameter.limit_rows=atoi(value); break;
case 7 : strcpy(sParameter.DEL_SQL,value); break;
case 8 : strcpy(sParameter.logfile,value);break;
default: break;
}//witch
break;
}//if
}
}
printf("IP:%s\n",sParameter.ip);
printf("USER:%s\n",sParameter.user);
printf("PROT:%s\n",sParameter.port);
printf("PAWD:%s\n",sParameter.passwd);
printf("SCHM:%s\n",sParameter.schema);
printf("TOTAL_SQL:%s\n",sParameter.TOTAL_SQL);
printf("LIMIT_ROWS:%d\n",sParameter.limit_rows);
printf("DEL_SQL:%s\n",sParameter.DEL_SQL);
printf("LOG_FILE_NAME:%s\n",sParameter.logfile);
}
MYSQL my_connection;
int connect_flag = 0;
mysql_init(&my_connection); //初始化链接
char* pHost;
char* pUser;
char* pPassword;
char* pSchema;
pHost=sParameter.ip;
pUser=sParameter.user;
pPassword=sParameter.passwd;
pSchema = sParameter.schema;
if (mysql_real_connect(&my_connection,pHost,pUser,pPassword,pSchema,atoi(sParameter.port),NULL,CLIENT_FOUND_ROWS))
{
printf("Mysql Connect succent!\n");
connect_flag = 1;
}
else
{
printf("Mysql Connect succent!\n");
connect_flag = 0;
}
if ( connect_flag == 1)
{
MYSQL_RES* res_ptr; //返回结果集指针
MYSQL_ROW result_row; //返回行
int res,row,column; //行列
long affected_rows = 0;
uint8 Count_Rows = 0;
mysql_query(&my_connection,"set names utf8mb4"); //设置字符集
res =mysql_query(&my_connection,sParameter.TOTAL_SQL); //执行查询语句
affected_rows = mysql_affected_rows(&my_connection);
if(res) { printf("Query Faile %s\n",mysql_error(&my_connection)); } //返回错误
else
{
res_ptr = mysql_store_result(&my_connection); //获取这次结果集
if (res_ptr)
{
row=mysql_num_rows(res_ptr); //获取行数
column=mysql_num_fields(res_ptr); //获取列数
MYSQL_FIELD* FIELD_NAME_ARRY=mysql_fetch_fields(res_ptr); //获取列名
for (int c=0; c < column; c++)
{
printf("%s\t",FIELD_NAME_ARRY[c].name);
}
printf("\n");
for(int i=1; i< row+1;i++) //打印行内容
{
result_row= mysql_fetch_row(res_ptr); //提取行到行变量 提取了 MYSQL服务器端就被清空,只能提取一次
for (int j=0; j < column;j++)
{
printf("%s\t",result_row[j]); //从行变量 获取列的VALUE
}
printf("\n");
}
//result_row= mysql_fetch_row(res_ptr); //提取行到行变量
Count_Rows = atoi(result_row[0]);
printf("Count_Rows:%d\n",Count_Rows);
printf("Count_times:%d\n",Count_Rows/sParameter.limit_rows+1);
}
}
int iLoopTimes = Count_Rows/sParameter.limit_rows+1;
strcat(sParameter.DEL_SQL," ");
strcat(sParameter.DEL_SQL,"limit");
strcat(sParameter.DEL_SQL," ");
char sLimitRows[10];
sprintf(sLimitRows,"%d",sParameter.limit_rows);
strcat(sParameter.DEL_SQL,sLimitRows);
for ( int i=0 ; i<iLoopTimes; i++)
{
res =mysql_query(&my_connection,sParameter.DEL_SQL); //执行删除语句
if(res) { printf("Delete Faile %s\n",mysql_error(&my_connection)); }
else
{
affected_rows = mysql_affected_rows(&my_connection);
printf("Affected row:%d\n",affected_rows);
}
}
}
mysql_close(&my_connection);
}
//---------------------------------------------------------------------------------------------------------------------
int ReadLine( FILE* pFileHandle, char *Keys[],const int KeysLength,Tparameter* pParameter)
{
char LineBuf [2049]; //临时缓存区
char ValueBuf [2049]; //临时缓存区
char KeyBuf[35];
memset(LineBuf,'\0',sizeof(LineBuf)); //临时缓存区初始化
memset(KeyBuf,'\0',sizeof(KeyBuf));
memset(ValueBuf,'\0',sizeof(ValueBuf));
int iLimitRows=0;
if (pFileHandle != NULL)
{
while(!feof(pFileHandle)) //没有读到文件尾则循环读取
{
fgets(LineBuf,2049,pFileHandle); //读取下行到BUF中
if ( (LineBuf[0]=='#')||(LineBuf[0]=='\0') || (LineBuf[0]=='\r') || (LineBuf[0]=='\n') || (LineBuf[0]==' ') ) //如果这行是注解,回车,换行,空格则跳过
{ continue ; }
else
{
for (int i=0;i<strlen(LineBuf);i++) //读取每一个字符
{
if ( LineBuf[i] == '=' ) //找到等号
{
for ( int j=0; j<i;j++) KeyBuf[j]=LineBuf[j]; //把该行内容读到返回变量中
for ( int k=1; k <= (strlen(LineBuf)-i);k++)
{
if (LineBuf[k+i] !='\n')
{
ValueBuf[k-1]=LineBuf[k+i]; //把该行内容读到返回变量中
}
else
break;
}
for (int f=0; f < KeysLength; f++)
if ( strcmp(KeyBuf,Keys[f]) == 0)
{
switch(f) // char* Keys[9]={"IPAD","USER","PROT","PAWD","SCHM","TOTAL_SQL","LIMIT_ROWS","DEL_SQL","LOG_FILE_NAME"};
{
case 0 : strcpy(pParameter->ip,ValueBuf);break;
case 1 : strcpy(pParameter->user,ValueBuf);break;
case 2 : strcpy(pParameter->port,ValueBuf);break;
case 3 : strcpy(pParameter->passwd,ValueBuf);break;
case 4 : strcpy(pParameter->schema,ValueBuf);break;
case 5 : strcpy(pParameter->TOTAL_SQL,ValueBuf); break;
case 6 : pParameter->limit_rows=atoi(ValueBuf); break;
case 7 : strcpy(pParameter->DEL_SQL,ValueBuf); break;
case 8 : strcpy(pParameter->logfile,ValueBuf);break;
default: break;
}//witch
break;
}//if
break;
}//if
}//for
}//else if
memset(LineBuf,'\0',sizeof(LineBuf));
memset(KeyBuf,'\0',sizeof(KeyBuf));
memset(ValueBuf,'\0',sizeof(ValueBuf));
}//while
return 0 ;
} //feof
return 1 ;
}
int ReadKeyValue( FILE* pFileHandle,int* plast_row,char* pKey, char *pValue) //参数说明 第一个是文件句柄,第二个是上次读的行数,第3个是返回读取内容,第4个是等号位置
{
char LineBuf[2049],KeyBuf[1024],ValueBuf[2049]; //临时缓存区
int buff_size,i,iCurRow;
iCurRow=1;
buff_size=0;
memset(LineBuf,'\0',sizeof(LineBuf));
memset(KeyBuf,'\0',sizeof(KeyBuf));
memset(ValueBuf,'\0',sizeof(ValueBuf));
//临时缓存区初始化
if (pFileHandle != NULL)
{
fseek(pFileHandle,0,0);
while(!feof(pFileHandle)) //没有读到文件尾则循环读取
{
if( iCurRow >= *plast_row) //正好读取到上次的位置时
{
fgets(LineBuf,2049,pFileHandle); //读取下行到BUF中
iCurRow++;
if ((LineBuf[0]=='#')||(LineBuf[0]=='\0')||(LineBuf[0]=='\r')||(LineBuf[0]=='\n')||(LineBuf[0]==' ')) //如果这行是注解,回车,换行,空格则跳过
{ continue ; }
else
{
for (i=0;i<strlen(LineBuf);i++) //读取每一个字符
{
if (LineBuf[i]=='=') //找到等号
{
for ( int j=0; j<i;j++) KeyBuf[j]=LineBuf[j]; //读取KEY
for ( int k=1; k <= (strlen(LineBuf)-i);k++)
{
if (LineBuf[k+i] !='\n')
{
ValueBuf[k-1]=LineBuf[k+i]; //读取VALUE
}
else break;
}
*plast_row=iCurRow;
strcpy(pKey,KeyBuf);
strcpy(pValue,ValueBuf);
return 0;
}
}
} //if # \r \n space charter
} // if last row > cur row
else
{
fgets(LineBuf,2049,pFileHandle); // 已读过的行,文件指针下移一行
iCurRow++;
}
} //while file read
}
return 1 ;
}
int GetFileRowNum( FILE* pFileHandle)
{
int iRow=0;
char buff[2048];
if (pFileHandle != NULL)
while (!feof(pFileHandle))
{
fgets(buff,2049,pFileHandle);
iRow++;
}
return iRow;
}
用C语言去操作MYSQL
c语言读取文本文件
C语言写文件C语言 地址变量 中级应用现代 C99, C11 标准下的 C 语言编程一篇讲清Linux下GCC编译C语言的参数C语言写文件FIX
C 语言的标准时间封装





