老哥,非常通俗易懂的mysql之插入和查询操作总结
在上一篇文章中,我们详细的分享了关于mysql如何进行远程登入以及在ubuntu上如何安装mysql。那么前期的工作基础,我们已经做好了,今天我们就来往数据库里面插入数据,同时又从数据读取数据,也就是查询数据库中的数据。
一、往数据库中插入数据:
1、在往数据库中插入数据之前,咋们要先做一些前期知识预备。在我们上面的图中,我们可以看到一个节点服务器(也就是我们代码实现业务的的地方,所以等下代码实现对数据库的插入,就是从这里开始操作的),然后我们要从这个节点服务器往数据库库服务器里面的数据库插入数据,那么我们这里就涉及一个概念叫做“数据库建模”,所谓的数据库建模说白了就是把所有数据通过sql语句(也就是数据库能够识别的语言),把某种数据格式存放到数据库中去(当然这里讲的不是很专业),也就是能够对数据库进行代码操作。
那么在之前呢,我们在mysql workbench里面进行创建一个数据库,并同时创建一个表格,以及进行插入数据:
CREATE DATABASE KING_DB;#创建一个数据库
SHOW DATABASES;
USE KING_DB; #使用数据库
CREATE TABLE TBL_USER (
U_ID INT PRIMARY KEY AUTO_INCREMENT,#创建一个主键
U_NAME VARCHAR(32),
U_GENGDER VARCHAR(8)
);#这里可以养成一个好习惯,在创建用户前面加TBL,别人就知道这个是一个表
SHOW TABLES; #显示table表
SELECT * FROM TBL_USER;#显示表中的数据
INSERT TBL_USER(U_NAME,U_GENGDER) VALUES('King', 'man');#插入数据
实际情景图:
注解:主键意思是唯一的。一个数据表中只能包含一个主键。你可以使用主键来查询数据
上面涉及到的VARCHAR的意思是:
创建表的语法格式:
插入数据语法格式:
2、代码操作设计到的api介绍:
(1)、在写代码操作之前这里要安装一个客户端程序,相当于链接库:
sudo apt-get install libmysqlclient-dev
txp@ubuntu:~$ sudo apt-get install libmysqlclient-dev
[sudo] password for txp:
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
binutils cpp cpp-4.8 gcc gcc-4.8 libasan0 libatomic1 libc-dev-bin libc6
libc6-dev libcloog-isl4 libgcc-4.8-dev libgomp1 libisl10 libitm1 libmpc3
libmpfr4 libquadmath0 libtsan0 linux-libc-dev manpages-dev zlib1g-dev
Suggested packages:
binutils-doc cpp-doc gcc-4.8-locales gcc-multilib make autoconf automake1.9
libtool flex bison gdb gcc-doc gcc-4.8-multilib gcc-4.8-doc libgcc1-dbg
libgomp1-dbg libitm1-dbg libatomic1-dbg libasan0-dbg libtsan0-dbg
libquadmath0-dbg glibc-doc
The following NEW packages will be installed:
binutils cpp cpp-4.8 gcc gcc-4.8 libasan0 libatomic1 libc-dev-bin libc6-dev
libcloog-isl4 libgcc-4.8-dev libgomp1 libisl10 libitm1 libmpc3 libmpfr4
libmysqlclient-dev libquadmath0 libtsan0 linux-libc-dev manpages-dev
zlib1g-dev
The following packages will be upgraded:
libc6
1 upgraded, 22 newly installed, 0 to remove and 49 not upgraded.
Need to get 24.7 MB of archives.
After this operation, 76.3 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
(2)、api介绍:
(1)mysql_init()
(2)mysql_real_connect()
(3)mysql_real_query()
(4)mysql_close()
读者一看,这里函数操作跟c语言一样,没错,我们这里是用c语言来对mysql进行操作的,下面我们讲解一下每个api的作用(说明这些操作函数都来自头文件"mysql.h"):
MYSQL *mysql_init(MYSQL *mysql)
注解:获得或初始化一个MYSQL结构,返回值是一个被始化的MYSQL*句柄, 在内存不足的情况下,返回NULL
这里MYSQLMYSQL结构代表一个数据库连接句柄,包含有关服务器的连接状态的信息,几乎所有函数都是用到它:
typedef struct st_mysql
{
NET net; /* Communication parameters */
unsigned char *connector_fd; /* ConnectorFd for SSL */
char *host,*user,*passwd,*unix_socket,*server_version,*host_info;
char *info, *db;
struct charset_info_st *charset;
MYSQL_FIELD *fields;
MEM_ROOT field_alloc;
my_ulonglong affected_rows;
my_ulonglong insert_id; /* id if insert on table with NEXTNR */
my_ulonglong extra_info; /* Not used */
unsigned long thread_id; /* Id for connection in server */
unsigned long packet_length;
unsigned int port;
unsigned long client_flag,server_capabilities;
unsigned int protocol_version;
unsigned int field_count;
unsigned int server_status;
unsigned int server_language;
unsigned int warning_count;
struct st_mysql_options options;
enum mysql_status status;
my_bool free_me; /* If free in mysql_close */
my_bool reconnect; /* set to 1 if automatic reconnect */
/* session-wide random string */
char scramble[SCRAMBLE_LENGTH+1];
my_bool unused1;
void *unused2, *unused3, *unused4, *unused5;
LIST *stmts; /* list of all statements */
const struct st_mysql_methods *methods;
void *thd;
/*
Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag
from mysql_stmt_close if close had to cancel result set of this object.
*/
my_bool *unbuffered_fetch_owner;
/* needed for embedded server - no net buffer to store the 'info' */
char *info_buffer;
void *extension;
} MYSQL;
然后是mysql_real_connect():
MYSQL *mysql_real_connect(MYSQL *mysql,
const char *host,
const char *user,
const char *passwd,
const char *db,
unsigned int port,
const char *unix_socket,
unsigned int client_flag);
注解:
函数功能:连接一个MySQL服务器
host表示MYSQL服务器的主机名或IP
user表示登录的用户名
passwd表示登录的密码
db表示要连接的数据库
port表示MySQL服务器的TCP/IP端口
unix_socket表示连接类型
client_flag表示MySQL运行ODBC数据库的标记
函数返回值:如果连接成功,就返回非0,不成功,返回0.
接着是mysql_real_query():
int mysql_query(MYSQL *mysql,const char *query,);
注解:我们这里的这个示例api跟mysql_real_query(),有一个差别,就是mysql_real_query()有三个参数,第三参数是就是第二个参数的长度(这里我们查看到这个函数具体原型);同时,两者的真正差别在于,mysql_query()预期的查询为指定的、由Null终结的字符串,而myql_real_query()预期的是计数字符串。如果字符串包含二进制数据(其中可能包含Null字节),就必须使用mysql_real_squery()。
函数功能:对指定的连接进行查询,查询成功返回0,不成功就是非0了。
最后mysql_close():
void mysql_close(MYSQL *mysql);
注解:函数功能是关闭一个服务器连接,并释放与连接相关的内存
二、实战演练:
上面我们已经介绍完了api,下面我们就来对数据库进行插入数据操作了:
1、数据插入:
#include <stdio.h>
#include <mysql.h>
#include <string.h>
#define KING_DB_SERVER_IP "192.168.40.154"
#define KING_DB_SERVER_PORT 3306
#define KING_DB_USERNAME "txp"
#define KING_DB_PASSWORD "1121518wo"
#define KING_DB_DEFAULTDB "KING_DB"
#define SQL_INSERT_TBL_USER "INSERT TBL_USER(U_NAME,U_GENGDER) VALUES('zttt', 'man');"
int main()
{
MYSQL mysql ;
if(NULL== mysql_init(&mysql))
{
printf("mysql_init : %s\n",mysql_error(&mysql));
return -1;
}
if(!mysql_real_connect(&mysql,
KING_DB_SERVER_IP,
KING_DB_USERNAME,
KING_DB_PASSWORD,
KING_DB_DEFAULTDB,
KING_DB_SERVER_PORT,NULL,0))
{
printf("mysql_real_connect : %s\n",mysql_error(&mysql));
return -2;
}
//mysql
if( mysql_real_query(&mysql,SQL_INSERT_TBL_USER,strlen(SQL_INSERT_TBL_USER)))
{
printf("mysql_real_query : %s\n",mysql_error(&mysql));
return -3;
}
mysql_close(&mysql);
return 0;
}
编译:
txp@ubuntu:~$ gcc -o mysql mysql.c -I /usr/include/mysql/ -lmysqlclient
然后我们在mysql workbench里面查看原本数据库中表中有哪些数据:
我们可以看到有11行,现在我们来运行一下:
txp@ubuntu:~$ ./mysql
txp@ubuntu:~$
再次查看 mysql workbench这边的变化:
你会看到多了一个行数据出来,没错,这行数据就是我们刚刚运行写的代码插入到数据库中的数据。
2、数据查询:
这里数据查询的意思,就是说我们从数据库中把数据取到我们的应用程序当中去(也就是我们刚才的那个节点服务器中去):具体实现步骤如下:
1、先发送sql语句
2、存储我们的结果
3、判断有多少行有多少列
4、最后就可以进行我们的数据抓取
#include <stdio.h>
#include <mysql.h>
#include <string.h>
#define KING_DB_SERVER_IP "192.168.40.154"
#define KING_DB_SERVER_PORT 3306
#define KING_DB_USERNAME "txp"
#define KING_DB_PASSWORD "1121518wo"
#define KING_DB_DEFAULTDB "KING_DB"
//#define SQL_INSERT_TBL_USER "INSERT TBL_USER(U_NAME,U_GENGDER) VALUES('zttt', 'man');"
#define SQL_SELECT_TBL_USER "SELECT * FROM TBL_USER;"
//单独写个函数实现查询
int king_mysql_select(MYSQL *handle)
{
if( mysql_real_query(handle,SQL_SELECT_TBL_USER,strlen(SQL_SELECT_TBL_USER)))
{
printf("mysql_real_query : %s\n",mysql_error(handle));
return -1;
}
MYSQL_RES *res = mysql_store_result(handle);
if(NULL == res)
{
printf(" mysql_store_result : %s\n",mysql_error(handle));
return -2;
}
int rows = mysql_num_rows(res);
printf("rows: %d\n",rows);
int fields = mysql_num_fields(res);
printf("fields: %d\n",fields);
MYSQL_ROW row;
while(row = mysql_fetch_row(res))//查询每行每列中的数据
{
int i =0;
for(i=0;i<fields;i++)
{
printf("%s\t",row[i]);//这个行就相当于一个数组操作一样
}
printf("\n");
}
mysql_free_result(res);
return 0;
}
int main()
{
MYSQL mysql ;
if(NULL== mysql_init(&mysql))
{
printf("mysql_init : %s\n",mysql_error(&mysql));
return -1;
}
if(!mysql_real_connect(&mysql,
KING_DB_SERVER_IP,
KING_DB_USERNAME,KING_DB_PASSWORD,
KING_DB_DEFAULTDB,
KING_DB_SERVER_PORT,NULL,0))
{
printf("mysql_real_connect : %s\n",mysql_error(&mysql));
return -2;
}
king_mysql_select(&mysql);
#if 0
//mysql
if( mysql_real_query(&mysql,SQL_INSERT_TBL_USER,strlen(SQL_INSERT_TBL_USER)))
{
printf("mysql_real_query : %s\n",mysql_error(&mysql));
return -3;
}
#endif
mysql_close(&mysql);
return 0;
}
输出结果:
txp@ubuntu:~$ gcc -o mysql mysql-1.c -I /usr/include/mysql/ -lmysqlclient
txp@ubuntu:~$ ./mysql
rows: 12
fields: 3
1 txp man
2 txp man
3 txp man
4 Txp man
5 Txp man
6 Txp man
7 Txp man
8 Txp man
9 King man
10 King man
11 zttt man
12 zttt man
注解:上面又有几个陌生的api,下面我们具体来看他们的原型和用法:
结构体MYSQL_RES,MYSQL_RES结构代表返回行的查询结果(SELECT、SHOW、DESCRIBE等),从数据库读取数据,最后就是从MYSQL_RES中读取数据。MYSQL_RES定义如下:
typedef struct st_mysql_res {
my_ulonglong row_count;
MYSQL_FIELD *fields;
MYSQL_DATA *data;
MYSQL_ROWS *data_cursor;
unsigned long *lengths; /* column lengths of current row */
MYSQL *handle; /* for unbuffered reads */
const struct st_mysql_methods *methods;
MYSQL_ROW row; /* If unbuffered read */
MYSQL_ROW current_row; /* buffer to current row */
MEM_ROOT field_alloc;
unsigned int field_count, current_field;
my_bool eof; /* Used by mysql_fetch_row */
/* mysql_stmt_close() had to cancel this result */
my_bool unbuffered_fetch_cancelled;
void *extension;
} MYSQL_RES;
结构体MYSQL_ROWS
typedef struct st_mysql_rows {
struct st_mysql_rows *next; /* list of rows */
MYSQL_ROW data;
unsigned long length;
} MYSQL_ROWS;
然后接下来是mysql_store_result()函数:
MYSQL_RES *mysql_store_result(MYSQL *connection);
注解:这是在成功调用mysql_query之后使用此函数,这个函数将立刻保存在客户端中返回的所有数据。它返回一个指向结果集结构的指针,如果失败返回NULL
然后接下来是 mysql_num_rows和mysql_num_fields函数
unsigned int mysql_num_rows(MYSQL_RES *result);
unsigned int mysql_num_fields(MYSQL_RES *res);
注解:第一个函数功能是结果集中行的数量。
第二个函数功能是返回指定结果集中列的数量
最后是 mysql_fetch_row函数和 mysql_free_result
MYSQL_ROW mysql_fetch_row(MYSQL_RES *resutl);
void mysql_free_result(MYSQL_RES *result);
注解:第一个函数检索结果集的下一行。在mysql_store_result()之后使用时,如果没有要检索的行,mysql_fetch_row()返回NULL。在mysql_use_result()之后使用时,如果没有要检索的行或出现了错误,mysql_fetch_row()返回NULL。如果行中保存了调用mysql_fetch_row()返回的值,将按照row[0]到row[mysql_num_fields(result)-1],访问这些值的指针。行中的NULL值由NULL指针指明
第二个函数相当于释放内存
三、总结:
本期关于数据库的插入和查询,咋们就总结到这里了,我们下期再见。