zoukankan      html  css  js  c++  java
  • Linux使用C语言连接MYSQL

    1、连接例程:
    首先,使用mysql_init来初始化连接剧柄:
    #include

    初始化之后,你必须使用mysql_real_connect来向一个连接提供参数:
        MYSQL *mysql_real_connect(MYSQL *connection,//指向已经被mysql_init初始化过的结构
                    const char *server_host,//可以是主机名,也可以是IP地址(本地可以是localhost)
                    const char *sql_user_name,//使用者
                    const char *sql_password,//使用者密码(密码会再被传输的过程中加密)
                    const char *db_name,//数据库名字
                    unsigned int port_number,//NULL,这两个为默认值就行
                    const char *unix_socket_name,//0
                    unsigned int flags);//这是改变协议的特性,位模式进行OR操作
        如果无法连接,它将返回NULL。mysql_error函数可以提供又帮助的信息。
    使用完连接之后,通常在程序退出时,使用mysql_close:
    void mysql_close(MYSQL *connection);
    这将关闭连接。如果连接时由mysql_init建立的,mysql结构会被释放。指针将会失效并无法再次使用。逗留一个不需
    要的连接是对资源的浪费,但是重新打开连接也会带来额外的开销,所以你必须自己权衡何时使用这些选项。
    
    mysql_options例程(仅能在mysql_init和mysql_read_connect之间调用)可以设置一些选项:
    int mysql_options(MYSQL *connection,enum option_to_set,const char *argument);
    
    因为mysql_options一次只能设置一个选项,所以每设置一个选项就得调用它一次。你可以根据需要多次使用它,只
    要它出现在mysql_init和mysql_real_connect之间即可。并不是所有的选项都是char类型,因此它们必须被转换
    成const char *.  
    
    enum选项          实际参数类型          说明
    MYSQL_OPT_CONNECT_TIMEOUT   const unsigned int *        连接超时之前的等待秒数
    MYSQL_OPT_COMPRESS      None,使用NULL         网络连接中使用压缩机制
    MYSQL_INIT_COMMAND      const char *            每次连接建立后发送的命令
    一次成功的调用将返回0。因为它仅仅是用来设置标志,所以失败总是意味这使用了一个无效的选项。
    
    例子:
    如果要设置连接超时时间为7秒,我们使用的代码片段如下所示:
    
    unsigned int timeout=7;
        ...
        connection=mysql_init(NULL);
        ret=mysql_options(connection,MYSQL_OPT_CONNECT_TIMEOUT,(const char *)&timeout);
    
        if(ret){
            /*Handle error*/
        }
        connection=mysql_real_connect(connection ...);
    下面我们使用一个简洁的程序来测试一下:
    首先为用户设置一个新的密码(在下面的代码中,是本机上的rick的用户),然后创建要连接的数据库foo。
    
    $ mysql -u root -p
        mysql> grant all on *.* to rick@localhost identified by '123456'
    
        mysql> q
        $ mysql -u rick -p
        mysql> create database foo;
        mysql> q 
    使用sql文件进行批处理,这个文件为create_children.sql:
    
    create table children (
        childno int(11) not null auto_increment primary key,
        fname varchar(30),
        age int(11)
        );
    
        insert into children(childno,fname,age) values(1,'Jenny',21);
        insert into children(childno,fname,age) values(2,'Andrew',17);
        insert into children(childno,fname,age) values(3,'Gavin',8);
        insert into children(childno,fname,age) values(4,'DUncan',5);
        insert into children(childno,fname,age) values(5,'Alex',4);
        insert into children(childno,fname,age) values(6,'Adrian',9);
    重新登录:
    
    $ mysql -u rick -p foo //或者是:mysql -u rick --password=123456 foo
        mysql> source create_children.sql //或者是:. create_children.sql
    下面的程序connect1.c,它以用户名rick和密码123456来连接本机服务器上名为foo的数据库:
    
    #include <stdlib.h>
        #include <stdio.h>
    
        #include "mysql.h"
    
        int main(int argc,char *argv[]){
            MYSQL *conn_ptr;
    
            conn_ptr=mysql_init(NULL);//一般都是传递一个NULL
            if(!conn_ptr){
                fprintf(stderr,"mysql_init failed
    ");
                return EXIT_FAILURE;
            }
    
            conn_ptr=mysql_real_connect(conn_ptr,"localhost","rick","123456","foo",0,NULL,0);
            if(conn_ptr){
                printf("COnnection success
    ");
            }
            else
            {
                printf("Connection failed
    ");
            }
            mysql_close(conn_ptr);
    
            return EXIT_SUCCESS;
        }
    下面是编译:
    1、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql  -L/usr/lib64/mysql  -lmysqlclient -o connect1
    我的是这种
    2、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql  -lmysqlclient -o connect1
    
    执行:(到这里你就成功了)
    $ ./connect1
    Connection success
    

    错误处理
    unsigned int mysql_errno(MYSQL *connection);
    char *mysql_error(MYSQL *connection);
    你可以通过调用mysql_error并传递连接结构来获得错误码,它通常都是非0值。
    如果未设定错误码,它将返回0.
    每次调用库都会跟新错误码,所以你只能得到最后一个执行命令的错误码。

    但是上面两个检查是例外,它们不会导致错误码的更新。
    
    mysql_errno的返回值就是实际错误码,它们在头文件errmsg.h或者mysqld_error.h中定义。
    这两个文件都可以在MySQL的include目录中找到。
    前者报告客户端错误,后者关注服务器错误。
    
    如果你喜欢文本错误信息,也可以调用mysql_error,它提供了有意义的文本信息而不是单调的错误码。
    
    下面的connect2.c它例出了如何使用非动态分配的连接结构,以及如何编写一些基本的错误处理代码:
    
    #include <stdlib.h>
        #include <stdio.h>
        #include <mysql.h>
    
        int main(int argc,char *argv[])
        {
            MYSQL my_connection;
    
            mysql_init(&my_connection);
            if(mysql_real_connect(&my_connection,"localhost","rick","I do not know","foo",0,NULL,0)){
                printf("Connection success
    ");
                mysql_close(&my_connection);
            }
            else
            {
                fprintf(stderr,"Connection_failed
    ");
                if(mysql_errno(&my_connection)){
                    fprintf(stderr,"Connection error %d: %s
    ",
                    mysql_errno(&my_connection),mysql_error(&my_connection));
                }
            }
            return EXIT_SUCCESS;
        }
    下面是编译:
    1、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql  -L/usr/lib64/mysql  -lmysqlclient -o connect1
    我的是这种
    2、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql  -lmysqlclient -o connect1
    
    执行:
    $ ./connect2
    Connection_failed
    Connection error 1045: Access denied for user 'rick'@'localhost' (using password: YES)
    

    执行SQL语句
    int mysql_query(MYSQL *connection,const char *query);
    成功,返回0.对于包含二进制数据的查询,你可以使用mysql_real_query。

    检查受影响的函数:
    my_ulonglong mysql_affected_rows(MYSQL *connection);
    
    例子:
    
    #include <stdlib.h>
            #include <stdio.h>
            #include <mysql.h>
    
            int main(int argc,char *argv[])
            {
                MYSQL my_connection;
                int res;
    
                mysql_init(&my_connection);
                if(mysql_real_connect(&my_connection,"localhost",
                            "rick","123456","foo",0,NULL,0)){
                    printf("Connection success
    ");
                    //当前是更新,此处可以替换为插入
                    //mysql_query(&my_connection,"insert into children(fname,age) values('Ann',3)");
                    res=mysql_query(&my_connection,"update children set age=4 where fname='Ann'");
                    if(!res){
                        printf("updated %lu rows
    ",(unsigned long)mysql_affected_rows(&my_connection));
                    }
                    else
                    {
                        fprintf(stderr,"update error %d: %s
    ",mysql_errno(&my_connection),mysql_error(&my_connection));
                    }
                    mysql_close(&my_connection);
                }
                else
                {
                    fprintf(stderr,"Connection failed
    ");
                    if(mysql_errno(&my_connection)){
                        fprintf(stderr,"Connection error %d: %s
    ",mysql_errno(&my_connection),mysql_error(&my_connection));
                    }
                }
                return EXIT_SUCCESS;
            }
    编译同上。
    
    但是你也可以使用更传统的报告:
    if(mysql_real_connect(&my_connection,"localhost","rick","123456","foo",0,NULL,CLIENT_FOUND_ROWS)){
    
    };
    

    发现插入的内容:
    atuo_increment类型的列,它由mysql自动分配ID。
    LAST_INSERT_ID()会发现每个用户对最后分配的值进行跟踪。

    实验:提取由AUTO_INCREMENT生成的ID
    
    MariaDB [foo]> insert into children(fname,age) values('Tom',13);
        Query OK, 1 row affected (0.00 sec)
    
        MariaDB [foo]> show tables;
        +---------------+
        | Tables_in_foo |
        +---------------+
        | children      |
        +---------------+
        1 row in set (0.00 sec)
    
        MariaDB [foo]> select last_insert_id();
        +------------------+
        | last_insert_id() |
        +------------------+
        |                2 |
        +------------------+
        1 row in set (0.00 sec)
    每次插入一行,MySQL就分配一个新的id值并且跟踪它,使得你可以用LAST_INSERT_ID()来提取它。
    
    实验:在C程序中使用自动分配的ID
    程序名字:insert2.c
    
    #include <stdlib.h>
        #include <stdio.h>
    
        #include <mysql.h>
    
        int main(int argc,char *argv[]){
            MYSQL my_connection;
            MYSQL_RES *res_ptr;
            MYSQL_ROW sqlrow;
    
            int res;
    
            mysql_init(&my_connection);
            if(mysql_real_connect(&my_connection,"localhost","rick","123456","foo",0,NULL,0)){
                printf("Connection success
    ");
    
                res=mysql_query(&my_connection,"insert into children(fname,age) values('Robert',7)");
                if(!res){
                    printf("Inserted %lu rows
    ",(unsigned long)mysql_affected_rows(&my_connection));
                }
                else{
                    fprintf(stderr,"Insert error %d: %s
    ",mysql_errno(&my_connection),mysql_error(&my_connection));
                }
    
                res=mysql_query(&my_connection,"select last_insert_id()");
                if(res){
                    printf("select error: %s
    ",mysql_error(&my_connection));
                }
                else{
                    /*
                    对于成功检索数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN),必须调用mysql_store_result()或
                    mysql_use_result()。mysql_use_result()将初始化结果集检索,但并不像mysql_store_result()那样将结果集实际
                    读取到客户端。它必须通过对mysql_fetch_row()的调用,对每一行分别进行检索
                    */
                    //MYSQL_RES *mysql_use_result(MYSQL *mysql)
                    res_ptr=mysql_use_result(&my_connection);
                    if(res_ptr){
                        //array mysql_fetch_row(int result) 
                        //获取查询结果集,其区别在于函数的返回值不是一个字符串,而是一个数组
                        while((sqlrow=mysql_fetch_row(res_ptr))){
                            printf("We inserted childno %s
    ",sqlrow[0]);
                        }
                        //void mysql_free_result() 函数释放结果内存。
                        mysql_free_result(res_ptr);
                    }
                }
    
                mysql_close(&my_connection);
            }
            else{
                fprintf(stderr,"Connection failed
    ");
                if(mysql_errno(&my_connection)){
                    fprintf(stderr,"Connection error %d: %s
    ",
                        mysql_errno(&my_connection),mysql_error(&my_connection));
                }
            }
            return EXIT_SUCCESS;
        }
    下面是编译:
    1、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql  -L/usr/lib64/mysql  -lmysqlclient -o connect1
    我的是这种
    2、gcc -I/usr/include/mysql connect1.c -L/usr/lib/mysql  -lmysqlclient -o connect1
    

    返回数据的语句:
    你可以使用mysql_query来发送SQL语句,然后,你使用mysql_store_result或者mysql_use_result提取数据。
    接着,你将使用一些mysql_fetch_row调用来处理数据。
    最后,使用mysql_free_result释放查询占用的内存资源。

    mysql_use_result和mysql_store_result的区别主要在于,你想一次返回一行数据,还是一次返回所有的结果。
    1、一次提取所有数据的函数
    MYSQL_RES *mysql_store_result(MYSQL *connection);
    
    调用mysql_num_rows来得到返回记录的数据,我们希望这是个正数,但是如果没有返回行,这个值将是0:
    my_ulonglong mysql_num_rows(MYSQL_RES *result);
    
    a.mysql_fetch_row:这个函数从使用mysql_store_result得到的结构结构中提取一行,并把它放到一个行结构中。当数据用完或者
    发生错误时返回NULL
    MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
    
    b.mysql_data_seek:这个函数用来在结果集中进行跳转,设置将会被下一个mysql_fetch_row操作返回的行。参数offset的值是一个行号,
    它必须在0到结果集总行数减1的范围内。传递0将会导致下一个mysql_fetch_row调用返回结果集中的第一行。
    void mysql_data_seek(MYSQL_RES *result,my_ulonglong offset);
    
    c.mysql_row_tell:这个函数返回一个偏移量,它用来表示结果集中的当前位置。
    MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result);
    
    d.但是,你可以这样使用它的返回值:
    MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result,MYSQL_ROW_OFFSET offset);
    
    e.完成了对数据的所有操作后,你必须明确的调用mysql_free_result来让MYSQL库完成善后处理:
    void mysql_free_result(MYSQL_RES *result);
    
    提取数据试验:
    
    #include <stdlib.h>
            #include <stdio.h>
    
            #include <mysql.h>
    
            MYSQL my_connection;
            MYSQL_RES *res_ptr;
            MYSQL_ROW sqlrow;
    
            int main(int argc,char *argv[]){
                int res;
    
                mysql_init(&my_connection);
                if(mysql_real_connect(&my_connection,"localhost","rick","123456","foo",0,NULL,0)){
                    printf("Connection success
    ");
    
                    res=mysql_query(&my_connection,"select childno,fname,age from children where age>5");
                    if(res){
                        printf("select error: %s
    ",mysql_error(&my_connection));
                    }
                    else{
                        res_ptr=mysql_store_result(&my_connection);
                        if(res_ptr){
                            printf("Retrieved %lu rows
    ",(unsigned long)mysql_num_rows(res_ptr));
    
                            while(sqlrow=mysql_fetch_row(res_ptr)){
                                printf("Fetched data...
    ");
                            }
                            if(mysql_errno(&my_connection)){
                                fprintf(stderr,"Retrive error: %s
    ",mysql_error(&my_connection));
                            }
                            mysql_free_result(res_ptr);
                        }
                    }
                    mysql_close(&my_connection);
                }
                else
                {
                    fprintf(stderr,"Connection failed
    ");
                    if(mysql_errno(&my_connection)){
                        fprintf(stderr,"Connection error %d: %s
    ",
                            mysql_errno(&my_connection),mysql_error(&my_connection));
                    }
                }
                return EXIT_SUCCESS;
            }
    编译:
    gcc -I/usr/include/mysql insert3.c -L/usr/lib/mysql  -L/usr/lib64/mysql -L/usr/lib/mysql -lmysqlclient -o insert3
    

    一次提取一行数据:
    MYSQL_RES *mysql_use_result(MYSQL *connection);

    处理返回的数据:
    mysql_field_count函数提供了一些关于查询结果的基本信息。它接受连接对象,并返回结果集中的字段数目:
    unsigned int mysql_field_count(MYSQL *connection);

    下面是简单的打印数据的代码:
    
    void display_row(){
            unsigned int field_count;
    
            field_count=0;
            while(field_count<mysql_field_count(&my_connection)){
                printf("%s ",sqlrow(field_count));
                field_count++;
            }
            printf("
    ");
        }

    使用mysql_fetch_field()来同时将元数据和数据提取到一个新的结构中:
    MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result);

    #include <stdlib.h>
        #include <stdio.h>
    
        #include <mysql.h>
    
        MYSQL my_connection;
        MYSQL_RES *res_ptr;
        MYSQL_ROW sqlrow;
    
        void display_header();
        void display_row();
    
    
        int main(int argc, char *argv[]) {
           int res;
           int first_row = 1; /* Used to ensure we display the row header exactly once when data is successfully retrieved */
    
    
           mysql_init(&my_connection);  
           if (mysql_real_connect(&my_connection, "localhost", "rick", 
                                                    "123456", "foo", 0, NULL, 0)) {
              printf("Connection success
    ");
    
              res = mysql_query(&my_connection, "SELECT childno, fname, age FROM children WHERE age > 5");
    
              if (res) {
             fprintf(stderr, "SELECT error: %s
    ", mysql_error(&my_connection));
              } else {
             res_ptr = mysql_use_result(&my_connection);
             if (res_ptr) {
                while ((sqlrow = mysql_fetch_row(res_ptr))) {
                   if (first_row) {
                      display_header();
                      first_row = 0;
                   }
                   display_row();
                }
                if (mysql_errno(&my_connection)) {
                 fprintf(stderr, "Retrive error: %s
    ",
                                    mysql_error(&my_connection));
                }
                mysql_free_result(res_ptr);
             }
              }
              mysql_close(&my_connection);
           } else {
              fprintf(stderr, "Connection failed
    ");
              if (mysql_errno(&my_connection)) {
            fprintf(stderr, "Connection error %d: %s
    ",
                                    mysql_errno(&my_connection),
                                    mysql_error(&my_connection));
            }
              }
    
           return EXIT_SUCCESS;
        }
    
    
        void display_header() {
           MYSQL_FIELD *field_ptr;
    
           printf("Column details:
    ");
    
           while ((field_ptr = mysql_fetch_field(res_ptr)) != NULL) {
              printf("	 Name: %s
    ", field_ptr->name);
              printf("	 Type: ");
              if (IS_NUM(field_ptr->type)) {
             printf("Numeric field
    ");
              } else {
             switch(field_ptr->type) {
                case FIELD_TYPE_VAR_STRING:
                   printf("VARCHAR
    ");
                break;
                case FIELD_TYPE_LONG: 
                   printf("LONG
    ");
                break;
                default:
                  printf("Type is %d, check in mysql_com.h
    ", field_ptr->type);
             } /* switch */
              } /* else */
    
              printf("	 Max width %ld
    ", field_ptr->length); /* Note on versions of MySQL before 4.0 the format should be %d, rather than %ld */
              if (field_ptr->flags & AUTO_INCREMENT_FLAG) 
             printf("	 Auto increments
    ");
              printf("
    ");
           } /* while */
        }
    
    
        void display_row() {
           unsigned int field_count;
    
           field_count = 0;
           while (field_count < mysql_field_count(&my_connection)) {
              if (sqlrow[field_count]) printf("%s ", sqlrow[field_count]);
              else printf("NULL");
              field_count++;
           }
           printf("
    ");
        }

    更多的函数:
    char *mysql_get_client_info(void) 返回客户端使用的库的版本信息
    char *mysql_get_host_info(MYSQL *connection) 返回服务器连接信息
    char *mysql_get_server_info(MYSQL *connection) 返回当前连接的服务器的信息
    char *mysql_info(MYSQL *connection); 返回最近执行的查询的信息,但是仅仅只对一些查询类型有效,通常是insert和updata
    int mysql_select_db(MYSQL *connection,const char *dbname)如果用户拥有合适的权限,则把默认数据库改成参数指定的数据库,成功返回0
    int mysql_shutdown(MYSQL *connection,enum mysql_enum_shutdown_level); 如果用户拥有合适的权限,则关闭连接的数据库服务器。目前关闭级别必须被设置为SHUTDOWN_DEFAULT.成功时返回0

    技术不分国界
  • 相关阅读:
    js获取 DOM 里所有图片(包括背景和iframe)
    php 和 js互相调用
    mac 权限
    node 启动命令
    three.js THREE.MeshLine.js 回显3D路径
    Vue2, Vue3 开发单一html页面区别
    前端布局,相关链接
    jq国际化jquery.i18n.properties使用
    资料
    其它工具
  • 原文地址:https://www.cnblogs.com/angels-yaoyao/p/12443606.html
Copyright © 2011-2022 走看看