之前我的一些有关于SQLServer学习的文章:
SQL Server学习(1)介绍与安装
SQL Server学习(2)创建数据库和数据表
SQLServer学习(3)导入导出数据表
SQLServer学习(4)给数据库、表生成SQL脚本
SQLServer学习(5)为SQLServer创建登录账户
SQLServer学习(6)C语言连接数据库
我的配置:
操作系统:Window10 x64
SQL Server 2016
IDE:Visual Studio 2017
这篇文章将介绍如何用C语言将TXT文本数据插入SQLServer数据库。
读取TXT文件内容 首先,抛开SQLServer数据库,单纯地用C语言实现读取TXT格式文本内容。
代码 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LINE 1024 struct data { int id; char name[10 ]; }person[1000 ];int main () { char buf[MAX_LINE]; FILE *fp; int len; int i=0 ; if ((fp = fopen("D:\\vs_project\\WriteTXT\\WriteTXT\\WriteTXT\\test.txt" , "r" )) == NULL ) { perror("fail to read" ); exit (1 ); } printf ("id\tname\n" ); while (fgets(buf, MAX_LINE, fp) != NULL ) { len = strlen (buf); buf[len - 1 ] = '\0' ; sscanf (buf,"%d,%s" , &person[i].id, &person[i].name); printf ("%d\t%s\n" , person[i].id, person[i].name); i++; } printf ("num:%d\n" , i); getchar(); fclose(fp); return 0 ; }
相关函数 perror()函数 void perror(const char *str)
把一个描述性错误消息输出到标准错误 stderr。首先输出字符串 str ,后跟一个冒号,然后是一个空格。
exit()函数 void exit(int status)
立即终止调用进程。任何属于该进程的打开的文件描述符都会被关闭,该进程的子进程由进程 1 继承,初始化,且会向父进程发送一个 SIGCHLD 信号。
fopen()函数 FILE *fopen(const char *filename, const char *mode)
使用给定的模式 mode 打开 filename 所指向的文件。
该函数返回一个 FILE 指针。否则返回 NULL,且设置全局变量 errno 来标识错误。
fgets()函数 char *fgets(char *str, int n, FILE *stream)
从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
str – 这是指向一个字符数组的指针,该数组存储了要读取的字符串。
n – 这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度。
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流。
sscanf()函数 int sscanf(const char *str, const char *format, ...)
从字符串读取格式化输入。
fscanf()函数 与sscanf()
函数类似,int fscanf(FILE *stream, const char *format, ...)
从流 stream 读取格式化输入。fscanf能正确操作的txt文件编码方式为ANSI,以下编码方式均不能使函数正常执行:UTF-8,Unicode,Unicode big endian。
报错 VS使用fopen()时可能会报如图错误“error C4996: ‘fopen’: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.”:
解决方法 (1)在VS中,在“解决方案资源管理器”中项目名上单击右键——选择“属性”。
(2)在属性页中的“预处理器”中添加预处理定义。
(3)把 _CRT_SECURE_NO_WARNINGS添加进去,确定保存 即可,再次运行就没有问题了。
结果 TXT文本文件里的内容,如图:
程序运行效果如图:
插入数据库 结合上一篇文章SQLServer学习(6)C语言连接数据库 将部分代码修改写成void insertData(int i)
函数,然后和上文读取TXT文本的代码写成int readTxt(char path[1024])
函数相结合即可。
代码 #include <stdio.h> #include <string.h> #include <windows.h> #include <sql.h> #include <sqlext.h> #include <sqltypes.h> #include <odbcss.h> #include <stdlib.h> #define MAX_LINE 1024 SQLINTEGER id; SQLCHAR name[20 ]; SQLINTEGER len_id, len_name;struct data { int id; char name[10 ]; }person[1000 ];int readTxt (char path[1024 ]) { char buf[MAX_LINE]; FILE *fp; int len; int i = 0 ; if ((fp = fopen(path, "r" )) == NULL ) { perror("fail to read" ); exit (1 ); } printf ("id\tname\n" ); while (fgets(buf, MAX_LINE, fp) != NULL ) { len = strlen (buf); buf[len - 1 ] = '\0' ; sscanf (buf, "%d,%s" , &person[i].id, &person[i].name); printf ("%d\t%s\n" , person[i].id, person[i].name); i++; } printf ("num:%d\n" , i); fclose(fp); return i; }void insertData (int i) { SQLRETURN retcode; SQLHENV henv; SQLHDBC hdbc; SQLHSTMT hstmt; retcode = SQLAllocHandle(SQL_HANDLE_ENV, NULL , &henv); retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER); retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); retcode = SQLConnect(hdbc, (SQLCHAR*)"SQLC" , SQL_NTS, (SQLCHAR*)"SQLC" , SQL_NTS, (SQLCHAR*)"SQLC123" , SQL_NTS); if ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO)) { printf ("insertDataBase success!\n" ); retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); SQLCHAR sql[] = "USE test2" ; retcode = SQLExecDirect(hstmt, sql, SQL_NTS); SQLCHAR sql1[] = "INSERT INTO test VALUES (?,?);" ; SQLINTEGER P = SQL_NTS; retcode = SQLPrepare(hstmt, sql1, SQL_NTS); retcode = SQLBindParameter(hstmt, 1 , SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 10 , 0 , &person[i].id, 0 , &P); retcode = SQLBindParameter(hstmt, 2 , SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 20 , 0 , &person[i].name, 20 , &P); retcode = SQLExecute(hstmt); if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) { printf ("insertData%d success!\n" ,i); } else { printf ("insertData wrong!\n" ); SQLDisconnect(hdbc); } } else { printf ("insertDatabase wrong!\n" ); SQLDisconnect(hdbc); } SQLFreeHandle(SQL_HANDLE_DBC, hdbc); SQLFreeHandle(SQL_HANDLE_ENV, henv); }int main () { int num; int i; char path[]="D:\\vs_project\\WriteTXT\\WriteTXT\\WriteTXT\\test.txt" ; num = readTxt(path); for (i = 0 ; i < num; i++) { insertData(i); } getchar(); return 0 ; }
相关函数 SQL Server Native Client ODBC 驱动程序基于准备好的 SQL 语句创建临时存储过程。存储过程是多次执行某个语句的有效方式,不过创建存储过程的开销要比执行简单语句高。一般规则是,如果应用程序将要提交 SQL 语句超过三次,需要考虑使用 SQLPrepare 和 SQLExecute 。在调用 SQLPrepare 之前使用 SQLBindParameter 绑定参数变量。
SQLRETURN SQLBindParameter ( SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNumber, SQLSMALLINT InputOutputType, SQLSMALLINT ValueType, SQLSMALLINT ParameterType, SQLULEN ColumnSize, SQLSMALLINT DecimalDigits, SQLPOINTER ParameterValuePtr, SQLLEN BufferLength, SQLLEN * StrLen_or_IndPtr) ;
结果 TXT文本内容为:
原数据库test表格中的内容为:
程序效果图:
程序执行后的test表格中的内容为:
参考连接:
菜鸟教程 - C 库函数 - perror()
菜鸟教程 - C 库函数 - exit()
菜鸟教程 - C 库函数 - fopen()
菜鸟教程 - C 库函数 - fgets()
百度经验 - VS2013中如何解决error C4996: ‘fopen’问题
Microsoft Docs - SQLBindParameter
CSDN博客 - SQLBindParameter 函数的参数解析及使用方法
初学,可能写的一些地方不对,欢迎指出。
如有问题,可以在评论区里讨论。如需转载,请注明出处,谢谢。