哪些網(wǎng)站是java開發(fā)的優(yōu)化關(guān)鍵詞的方法有哪些
**前言:**本節(jié)內(nèi)容介紹使用C/C++訪問數(shù)據(jù)庫, 包括對(duì)數(shù)據(jù)庫的增刪查改操作。 主要是學(xué)習(xí)一些接口的調(diào)用, 廢話不多說, 開始我們的學(xué)習(xí)吧!
ps:本節(jié)內(nèi)容比較容易, 友友們放心觀看哦!
目錄
準(zhǔn)備mysql庫
使用mysql庫?
編譯文件
官方API文檔
對(duì)象的創(chuàng)建和關(guān)閉
鏈接數(shù)據(jù)庫
下達(dá)sql指令
select語句
準(zhǔn)備mysql庫
其實(shí)我們?cè)L問mysql不只是使用命令行進(jìn)行訪問, 我們未來訪問數(shù)據(jù)庫一定是一個(gè)程序?qū)?shù)據(jù)庫進(jìn)行訪問, 而程序其實(shí)就是代碼。所以未來我們可以使用代碼來訪問數(shù)據(jù)庫, 這里我們使用C/C++代碼對(duì)數(shù)據(jù)庫進(jìn)行訪問。
首先我們創(chuàng)建一個(gè)非root級(jí)別用戶和一個(gè)數(shù)據(jù)庫:
然后我們要知道, 我們?cè)L問數(shù)據(jù)要有對(duì)應(yīng)的開發(fā)包, 這些開發(fā)包我們可以直接在apt里面找到下載安裝。
sudo apt install -y libmysqlclient-dev
安裝好了之后我們就能在/usr/include/路徑下面看到mysql目錄
這個(gè) 里面包含著我們需要的文件, 像什么mysql.h就是我們所需要的。
然后在/usr/lib/x86_64-linux-gnu里面也有我們的mysql的連接庫:
使用mysql庫
編譯文件
然后使用庫,系統(tǒng)會(huì)默認(rèn)搜索的路徑是/lib/include路徑, 然后我們要使用的mysql.h頭文件在/lib/include西面的/mysql目錄下面, 所以我們包含頭文件要使用mysql/mysql.h:
#include<mysql/mysql.h>
mysql_get_client_info函數(shù)可以打印當(dāng)前mysql的版本信息。
#include<iostream>
#include<mysql/mysql.h>
using namespace std;int main()
{cout << "mysql_client version: " << mysql_get_client_info() << endl; return 0;
}
然后編譯可能會(huì)出現(xiàn)問題:
這是因?yàn)橐驗(yàn)槲覀兙幾g的時(shí)候系統(tǒng)找不到鏈接的庫, 所以需要我們使用-l指令指定路徑:
-lmysqlclient;
然后就能運(yùn)行成功了:
官方API文檔
然后就是我們要對(duì)數(shù)據(jù)庫進(jìn)行增刪查改,我們可以去mysql的官方文檔進(jìn)行查看對(duì)應(yīng)的資料
先進(jìn)入官方網(wǎng)站,點(diǎn)擊文檔:
然后下滑找到并點(diǎn)擊C API:
然后點(diǎn)擊function就能看到我們常用的一些函數(shù)了:
知道了這些之后, 下面開始學(xué)習(xí)增刪查改:
對(duì)象的創(chuàng)建和關(guān)閉
#include<iostream>
#include<mysql/mysql.h>
using namespace std;int main()
{MYSQL* my = mysql_init(nullptr);if (nullptr){cerr << "init MySQL error" << endl;return 1;}mysql_close(my);return 0;
}
這里面的MYSQL類型就類似于我們C語言里面的FILE類型, 都是一個(gè)句柄。如果成功了就是返回一個(gè)非空的值, 就代表我們獲得了拒柄。
既然獲得句柄, 那么最后情況下還要關(guān)閉數(shù)據(jù)庫, 釋放一系列資源。 使用mysql_close函數(shù), 就類似于我們關(guān)閉文件的操作。
鏈接數(shù)據(jù)庫
在官方文檔中給出的mysql鏈接函數(shù)如下。
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 long client_flag)
其中的第一個(gè)參數(shù)就是我們剛剛獲取的句柄。 然后第二個(gè)參數(shù)就是登錄的mysql所在的ip地址, 這里我們采用本地環(huán)回;第三個(gè)參數(shù)就是就是使用的用戶名;第四個(gè)參數(shù)就是對(duì)應(yīng)用戶的密碼;第五個(gè)參數(shù)就是數(shù)據(jù)庫的名稱;第六個(gè)參數(shù)就是端口號(hào);剩下的參數(shù)默認(rèn)即可。返回值就是MYSQL*也就是句柄, 如果是nullptr就是連接失敗。
#include<iostream>
#include<mysql/mysql.h>
#include<string>
using namespace std;
const string host = "localhost";
const string user = "mian_yang";
const string passwd = "XXXXXXXXXXXXXXXX";
const string db = "school_book_manage";
const unsigned int port = 3306;int main()
{MYSQL* my = mysql_init(nullptr);if (nullptr){cerr << "init MySQL error" << endl;return 1;}//if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr){cerr << "connect error" << endl;return 0;}//cout << "connect success" << endl;mysql_close(my);return 0;
}
然后我們編譯一下運(yùn)行一下:
下達(dá)sql指令
然后我們就可以使用函數(shù)下達(dá)sql指令, 在官方文檔中給出的函數(shù)如下:
int
mysql_query(MYSQL *mysql,const char *stmt_str)
其中第一個(gè)參數(shù)就是我們的句柄。 然后第二個(gè)參數(shù)就是我們要下達(dá)的指令。返回值如果為零就執(zhí)行成功了, 如果不為零, 就執(zhí)行失敗了。然后下面是代碼:
#include<iostream>
#include<mysql/mysql.h>
#include<string>
using namespace std;
const string host = "localhost";
const string user = "mian_yang";
const string passwd = "MYhylk563_al36huz.6";
const string db = "school_book_manage";
const unsigned int port = 3306;int main()
{MYSQL* my = mysql_init(nullptr);if (nullptr){cerr << "init MySQL error" << endl;return 1;}//if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr){cerr << "connect error" << endl;return 0;}//cout << "connect success" << endl;string sql;while (true){cout << ">>";if (!getline(cin, sql) || sql == "quit") break;int n = mysql_query(my, sql.c_str());if (n == 0) {cout << sql << " success "<<endl;}else cout << sql << " error" << endl;}mysql_close(my);return 0;
}
運(yùn)行的時(shí)候我們就來測(cè)驗(yàn)一下進(jìn)行插入:
然后也可以看到我們的sql語句執(zhí)行成功了!
現(xiàn)在我們插入一下李四, 插入中文, 我們查看一下結(jié)果:
我們會(huì)看到李四被正常的插入進(jìn)去了。 這里博主要說的是, 對(duì)于mysql8.0來說, 博主使用的是mysql8.0, 這里使用插入函數(shù)插入中文會(huì)正常插入。 但是如果是5.7版本的mysql, 那么這里如果插入中文插入的就是一堆亂碼。所有的亂碼問題都是客戶端和服務(wù)器雙方?jīng)]有形成編碼一致。比如說服務(wù)端使用utf8, 而客戶端使用的是其他的編碼方式。編碼不一致,那么我編碼使用的是utf8, 你解碼使用的是其他的方式。 那么就亂碼了。
這里我們的8.0數(shù)據(jù)庫, 表編碼都是utf8mb4的,說明我們的客戶端也是utf8mb4的。如果我們?cè)O(shè)置成其他的再插入就是一堆亂碼, 這里試驗(yàn)一下:使用mysql_set_character_set函數(shù)設(shè)置解碼方式:
mysql_set_character_set(my, "latin1");
插入成功:
可以看到, 解碼出來就是一堆亂碼。
現(xiàn)在問題來了, 我們上面的插入試驗(yàn)成功了, select語句呢? 我們的select語句是查, 要打印給我們一系列信息。 這里博主可以說一下實(shí)驗(yàn)結(jié)果, 結(jié)果是執(zhí)行成功, 但是沒有打印結(jié)果。 其他的像update, delete操作都能執(zhí)行成功。 只有select 雖然執(zhí)行成功但是沒有給我們顯示信息, 這是因?yàn)槠渌膕ql語句都只需要執(zhí)行成功即可, 但是select語句還要進(jìn)行后續(xù)的處理, 比如打印。 所以select語句怎么處理呢?
select語句
我們查出來的是一種表結(jié)構(gòu)。 如果我們查出來有四條數(shù)據(jù), 那么就有四行。 如果我們查出來的表有四列屬性, 那么查出來就有四列。 我們要知道我們要查的是一些數(shù)據(jù)。 那么這些數(shù)據(jù)在mysql內(nèi)部就一定要有對(duì)應(yīng)的內(nèi)存空間保存這個(gè)數(shù)據(jù)。 mysql將所有的數(shù)據(jù)讀取出來的時(shí)候全部都當(dāng)作字符串了。 然后有一個(gè)MYSQL_RES對(duì)象,MYSQL_RES對(duì)象就是將這些數(shù)據(jù)進(jìn)行整合一下。 我們可以把MYSQL_RES對(duì)象看成一個(gè)數(shù)組的指針, 這個(gè)數(shù)組里面存儲(chǔ)的數(shù)據(jù)類型是char**類型。 數(shù)組的大小表示一共有多少條記錄。
然后這些元素都指向一個(gè)char*的數(shù)組:
這個(gè)char*元素指向的就是我們的表結(jié)構(gòu)里面的屬性元素。 所以未來我們就可以把MYSQL_RES堪稱一個(gè)char** XXX[]數(shù)組。
所以, 這個(gè)MYSQL_RES其實(shí)就是我們使用select語句之后返回的結(jié)果, 這個(gè)結(jié)果的集合就在MYSQL_RES對(duì)象中。 未來我們想要去除其中的對(duì)象, 我們需要先獲取這個(gè)結(jié)果集里面的行, 里面的列:
MYSQL_RES *
mysql_store_result(MYSQL *mysql); //獲得結(jié)果集
uint64_t
mysql_num_rows(MYSQL_RES *result); //獲取行
unsigned int
mysql_num_fields(MYSQL_RES *result); //獲取列
為了更好的遍歷, mysql提供了一種數(shù)據(jù)結(jié)構(gòu)MYSQL_ROW, 方便我們更好的遍歷, 以后我們就可以直接把這個(gè)RES結(jié)果集當(dāng)成一個(gè)二維數(shù)組來使用。這個(gè)MYSQL_ROW就相當(dāng)于迭代器, 我們每次調(diào)用, 它都可以自動(dòng)加。
MYSQL_ROW
mysql_fetch_row(MYSQL_RES *result);
然后我們不僅有數(shù)據(jù), 還有我們的列名(列屬性)所以我們就可以獲取一下列名:
MYSQL_FIELD *
mysql_fetch_fields(MYSQL_RES *result)
這個(gè)函數(shù)的返回值是一個(gè)結(jié)構(gòu)里, 這個(gè)結(jié)構(gòu)體里面有著列名稱、取別名后的原生列名稱、 屬于哪個(gè)表、屬于哪個(gè)數(shù)據(jù)庫等等:
未來我們想要的就是這個(gè)name字段。 我們?nèi)缓缶涂梢韵虮闅v數(shù)組一樣遍歷這個(gè)列屬性,打印出來列屬性。
所以, 下面為全部的代碼:
#include<iostream>
#include<mysql/mysql.h>
#include<string>
using namespace std;
const string host = "localhost";
const string user = "mian_yang";
const string passwd = "MYhylk563_al36huz.6";
const string db = "school_book_manage";
const unsigned int port = 3306;int main()
{MYSQL* my = mysql_init(nullptr);if (nullptr){cerr << "init MySQL error" << endl;return 1;}//if (mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr){cerr << "connect error" << endl;return 0;}//cout << "connect success" << endl;string sql = "select * from user";int n = mysql_query(my, sql.c_str());if (n == 0) cout << sql << " success" << endl;else {cerr << sql << " error" << endl;return 3;}//MYSQL_RES* res = mysql_store_result(my);if (res == nullptr) {cerr << "res error" << endl;return 4;}MYSQL_FIELD* fields = mysql_fetch_fields(res);my_ulonglong cols = mysql_num_rows(res);for (int i = 0; i < cols; i++){cout << fields[i].name << " ";}cout << endl; my_ulonglong rows = mysql_num_rows(res);for (int i = 0; i < rows; i++){MYSQL_ROW row = mysql_fetch_row(res);for (int j = 0; j < cols; j++){cout << row[j] << " ";}cout << endl;}mysql_close(my);return 0;
}
然后打印就打印出來了:
對(duì)于MYSQL_RES, 其實(shí)MYSQL_RES就是在內(nèi)存中申請(qǐng)了一大塊內(nèi)存空間, 所以最后我們還要free這塊空間。而上層用戶如果使用free釋放空間就會(huì)造成內(nèi)存泄漏或者使用內(nèi)部的原生指針太麻煩。 所以就提供了一個(gè)接口:
void
mysql_free_result(MYSQL_RES *result)
這個(gè)函數(shù)就是系統(tǒng)提供的釋放我們的結(jié)果集。
--------------------------------------------------------------------------------------------------------------------------------
——————以上就是本節(jié)全部?jī)?nèi)容哦, 如果對(duì)友友們有幫助的話可以關(guān)注博主, 方便學(xué)習(xí)更多知識(shí)哦!!!