C/C++代碼操作MySQL數(shù)據(jù)庫詳細步驟
簡單嘗試使用c語言的庫對mysql的數(shù)據(jù)進行增刪改查
1.新增數(shù)據(jù)庫和表
剛開始數(shù)據(jù)庫沒有設(shè)定密碼和用戶,直接用root用戶登錄
mysql -uroot;
創(chuàng)建一個hello
數(shù)據(jù)庫,并進入這個數(shù)據(jù)庫
create database hello; use hello;
創(chuàng)建一個stu_student
數(shù)據(jù)表
create table stu_test( id int primary key auto_increment, name varchar(30), age int, score decimal(4,2) );
其中第一個id的類型是int,并設(shè)置為了auto_increment
,每次插入數(shù)據(jù)的時候它都會自增。
name是字符串類型,age是int類型,score分數(shù)是浮點類型
decimal(4,2) 表示的范圍是 -99.99 ~ 99.99 decimal(4,2)unsigned 表示的范圍是 0 ~ 99.99
到這里,前期的準備就完成了
2.接口簡單認識
依照注釋,簡單認識一下mysql庫的一些接口
//頭文件 #include <mysql/mysql.h> //Mysql操作句柄初始化 MYSQL *mysql_init(MYSQL *mysql); //參數(shù)為空則動態(tài)申請句柄空間進行初始化 //失敗返回NULL //連接mysql服務(wù)器 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); //mysql--初始化完成的句柄 //host---連接的mysql服務(wù)器的地址 //user---連接的服務(wù)器的用戶名 //passwd-連接的服務(wù)器的密碼 //db ----默認選擇的數(shù)據(jù)庫名稱 //port---連接的服務(wù)器的端口: 默認0是3306端口 //unix_socket---通信管道文件或者socket文件,通常置NULL //client_flag---客戶端標志位,通常置0 //返回值:成功返回句柄,失敗返回NULL //設(shè)置當前客戶端的字符集 int mysql_set_character_set(MYSQL *mysql, const char *csname) //mysql--初始化完成的句柄 //csname--字符集名稱,通常:"utf8" //返回值:成功返回0, 失敗返回非0 //選擇操作的數(shù)據(jù)庫 int mysql_select_db(MYSQL *mysql, const char *db) //mysql--初始化完成的句柄 //db-----要切換選擇的數(shù)據(jù)庫名稱 //返回值:成功返回0, 失敗返回非0 //執(zhí)行sql語句 int mysql_query(MYSQL *mysql, const char *stmt_str) //mysql--初始化完成的句柄 //stmt_str--要執(zhí)行的sql語句 //返回值:成功返回0, 失敗返回非0 //保存查詢結(jié)果到本地 MYSQL_RES *mysql_store_result(MYSQL *mysql) //mysql--初始化完成的句柄 //返回值:成功返回結(jié)果集的指針, 失敗返回NULL //獲取結(jié)果集中的行數(shù)與列數(shù) uint64_t mysql_num_rows(MYSQL_RES *result); //result--保存到本地的結(jié)果集地址 //返回值:結(jié)果集中數(shù)據(jù)的條數(shù); unsigned int mysql_num_fields(MYSQL_RES *result) //result--保存到本地的結(jié)果集地址 //返回值:結(jié)果集中每一條數(shù)據(jù)的列數(shù); //遍歷結(jié)果集 MYSQL_ROW mysql_fetch_row(MYSQL_RES *result) //result--保存到本地的結(jié)果集地址 //返回值:實際上是一個char **的指針,將每一條數(shù)據(jù)做成了字符串指針數(shù)組 row[0]-第0列 row[1]-第1列 //并且這個接口會保存當前讀取結(jié)果位置,每次獲取的都是下一條數(shù)據(jù) //釋放結(jié)果集 void mysql_free_result(MYSQL_RES *result) //result--保存到本地的結(jié)果集地址 //返回值:void //關(guān)閉數(shù)據(jù)庫客戶端連接,銷毀句柄: void mysql_close(MYSQL *mysql) //獲取mysql接口執(zhí)行錯誤原因 const char *mysql_error(MYSQL *mysql)
因為mysql是一個動態(tài)庫,所以編譯的時候,需要加上庫名的鏈接
g++ test.cpp -o test -lmysqlclient
在我的系統(tǒng)下,MySQL的庫是在/usr/lib64
目錄下的,所以我不需要額外指定庫的路徑。如果你的系統(tǒng)該目錄下沒有libmysqlclient.so
,則需要找到庫安裝的路徑,使用-L
命令指定該路徑
g++ test.cpp -o test -L/path/to/mysql/lib -lmysqlclient
3.代碼
開始寫代碼,一步一步認識mysql的各個接口
3.1 連接數(shù)據(jù)庫
因為我的數(shù)據(jù)庫都是默認的環(huán)境,所以不需要賬戶的密碼,按如下宏定義一下我們需要操作的數(shù)據(jù)庫信息,方便后續(xù)的修改
#include <mysql/mysql.h> #define HOST "127.0.0.1" #define PORT 3306 #define USER "root" #define PASSWD "" #define DBNAME "hello"
第一步,是用init來初始化一個MYSQL
的結(jié)構(gòu)體,并用一個指針來接收;
第二步,用mysql_real_connect
函數(shù)來進行數(shù)據(jù)庫的連接,填入我們剛剛的宏定義即可。
第三步,因為在最初配置mariadb
的環(huán)境時,為了更好的支持中文,我們將數(shù)據(jù)庫的字符集設(shè)置為了utf8,代碼中也需要同步修改,避免因為編碼問題產(chǎn)生的數(shù)據(jù)亂碼
最后一步,銷毀mysql結(jié)構(gòu)體
int main() { // 連接數(shù)據(jù)庫 // 初始化 MYSQL *mysql = mysql_init(nullptr); if (mysql == nullptr) // 返回值為空代表init失敗 { cerr << "[ERR] init mysql handle failed!\n"; return -1; } // 連接 cout << "[INFO] connect to " << HOST << ":" << PORT << " " << USER << " " << DBNAME << endl; // 第一個參數(shù)為輸出型參數(shù)。返回值為MYSQL的起始地址,如果錯誤返回NULL if (mysql_real_connect(mysql, HOST, USER, PASSWD, DBNAME, PORT, nullptr, 0) == nullptr) { cerr << "[ERR] mysql connect error: " << mysql_error(mysql) << endl; return -1; } // 配置為和數(shù)據(jù)庫同步的utf8字符集 mysql_set_character_set(mysql, "utf8"); // 到這里就已經(jīng)成功了 cout << "[INFO] mysql database connect success!" << endl; // 關(guān)閉連接 mysql_close(mysql); return 0; }
編譯執(zhí)行,成功鏈接上了數(shù)據(jù)庫
$ make g++ test.cpp -o test -lmysqlclient $ ./test [INFO] connect to 127.0.0.1:3306 root hello [INFO] mysql database connect success!
3.2 增加鍵值
下面要做的,就是給已有表新增一個鍵值
需要注意的是,mysql的代碼操作,實際上也是需要使用sql語句的(這點我覺得好麻煩)
插入語句如下,括號中的鍵值應(yīng)該和數(shù)據(jù)庫中表的鍵值一一對應(yīng)
insert into stu_test value (null,'牛爺爺',50,64.6);
所以我們要做的,就是寫一個函數(shù),將傳入的參數(shù)合并成一個sql語句,傳入mysql進行處理
// 將double轉(zhuǎn)為string std::string double2string(const double& d) { std::stringstream s_tmp; s_tmp << d; std::string s = s_tmp.str(); return s; } int add_key_to_stu(MYSQL *mysql,const std::string& name,int age,double score) { // 1.將傳入的參數(shù)處理為一個完整的sql語句 // 因為第一個編號參數(shù),配置的是自增,所以需要傳入null std::string sql_cmd = "insert into stu_test value (null,'"; sql_cmd+= name; sql_cmd+= "',"; sql_cmd+= std::to_string(age); sql_cmd+= ","; sql_cmd+= double2string(score); sql_cmd+= ");"; cout << "[INFO] " << sql_cmd << endl; // 2.執(zhí)行語句 int ret = mysql_query(mysql,sql_cmd.c_str()); if(ret!=0) { cerr << "[ERR] mysql insert error: " << mysql_error(mysql) << endl; } return ret; }
如下代碼測試
// 添加一個數(shù)據(jù) add_key_to_stu(mysql,"牛爺爺",50,64.6); add_key_to_stu(mysql,"小圖圖",5,72.8);
可以看到,成功運行!
$ ./test [INFO] connect to 127.0.0.1:3306 root hello [INFO] mysql database connect success! [INFO] insert into stu_test value (null,'牛爺爺',50,64.6); [INFO] insert into stu_test value (null,'小圖圖',5,72.8);
進入mysql命令行,使用如下命令,即可查詢到已有的鍵值
select * from stu_test;
可以看到,處理成功!
+----+-----------+------+-------+ | id | name | age | score | +----+-----------+------+-------+ | 1 | 牛爺爺 | 50 | 64.60 | | 2 | 小圖圖 | 5 | 72.80 | +----+-----------+------+-------+ 2 rows in set (0.001 sec)
3.3 修改已有鍵值
sql語句如下,修改當前數(shù)據(jù)庫中,stu_test
表中name為牛爺爺的條目的成績?yōu)?0
update stu_test set score=70 where name='牛爺爺';
// 修改已有學(xué)生的成績 int mod_score_in_stu(MYSQL *mysql,const std::string& name,double score) { std::string sql_cmd = "update "; sql_cmd += TABLENAME; sql_cmd += " set score="; sql_cmd += double2string(score); sql_cmd += " where name='"; sql_cmd += name; sql_cmd += "';"; cout << "[INFO] " << sql_cmd << endl; // 2.執(zhí)行語句 int ret = mysql_query(mysql,sql_cmd.c_str()); if(ret!=0) { cerr << "[ERR] mysql mod_score error: " << mysql_error(mysql) << endl; } return ret; }
可以看到,執(zhí)行成功了之后,牛爺爺?shù)某煽儼l(fā)生了變化
$ ./test [INFO] connect to 127.0.0.1:3306 root hello [INFO] mysql database connect success! [INFO] update stu_test set score=70 where name='牛爺爺';
MariaDB [hello]> select * from stu_test; +----+-----------+------+-------+ | id | name | age | score | +----+-----------+------+-------+ | 1 | 牛爺爺 | 50 | 64.60 | | 2 | 小圖圖 | 5 | 72.80 | +----+-----------+------+-------+ 2 rows in set (0.001 sec) MariaDB [hello]> select * from stu_test; +----+-----------+------+-------+ | id | name | age | score | +----+-----------+------+-------+ | 1 | 牛爺爺 | 50 | 70.00 | | 2 | 小圖圖 | 5 | 72.80 | +----+-----------+------+-------+ 2 rows in set (0.000 sec)
如果想修改其他鍵值,也是依照此步驟進行。
在實際場景中,一個數(shù)據(jù)條目肯定會有一個鍵值是不變的。比如在我的學(xué)生表中,假定每一個學(xué)生的名字都不變,我們就可以根據(jù)name字段來查找鍵值,對之進行其他值的修改。
如果真要嚴肅起來,用名字來查找肯定是不行的,我們應(yīng)該給每一個學(xué)生都生成一個學(xué)號或UID,用這個id來進行檢索。修改數(shù)據(jù)之前,都需要知道目標數(shù)據(jù)的uid值,才能修改。
3.4 刪除鍵值
如下語句,在test_tb
表中,刪除名字為張三的鍵值
delete from test_tb where name='張三';
在刪除之前,我又給數(shù)據(jù)庫新增了一個鍵值
MariaDB [hello]> select * from stu_test; +----+-----------+------+-------+ | id | name | age | score | +----+-----------+------+-------+ | 1 | 牛爺爺 | 50 | 70.00 | | 2 | 小圖圖 | 5 | 72.80 | | 3 | 大司馬 | 42 | 87.30 | +----+-----------+------+-------+ 3 rows in set (0.001 sec)
下面我要用代碼,刪除掉牛爺爺
// 刪除鍵值(根據(jù)名字) int del_key_in_stu(MYSQL *mysql,const std::string& name) { std::string sql_cmd = "delete from "; sql_cmd += TABLENAME; sql_cmd += " where name='"; sql_cmd += name; sql_cmd += "';"; cout << "[INFO] " << sql_cmd << endl; // 執(zhí)行語句 int ret = mysql_query(mysql,sql_cmd.c_str()); if(ret!=0) { cerr << "[ERR] mysql mod_score error: " << mysql_error(mysql) << endl; } return ret; }
// 刪除已有鍵值 del_key_in_stu(mysql,"牛爺爺");
編譯執(zhí)行
$ ./test [INFO] connect to 127.0.0.1:3306 root hello [INFO] mysql database connect success! [INFO] delete from stu_test where name='牛爺爺';
牛爺爺被刪掉了
MariaDB [hello]> select * from stu_test; +----+-----------+------+-------+ | id | name | age | score | +----+-----------+------+-------+ | 2 | 小圖圖 | 5 | 72.80 | | 3 | 大司馬 | 42 | 87.30 | +----+-----------+------+-------+ 2 rows in set (0.000 sec)
3.4.1 關(guān)于自增的id
此時再插入一個新的鍵值,可以看到id并么有把空余的1給補上,而是從4開始繼續(xù)往后增加
MariaDB [hello]> select * from stu_test; +----+-----------+------+-------+ | id | name | age | score | +----+-----------+------+-------+ | 2 | 小圖圖 | 5 | 72.80 | | 3 | 大司馬 | 42 | 87.30 | | 4 | 樂迪 | 32 | 99.00 | +----+-----------+------+-------+ 3 rows in set (0.001 sec)
知道這一點就行
3.5 查詢
對于數(shù)據(jù)庫而言,查詢也是一個高頻操作
select * from tb where name=key;
上面的語句,是在數(shù)據(jù)庫表tb中查找鍵值name為key的的數(shù)據(jù)
// 返回用戶的所有信息,name為空返回所有 void get_all_in_stu(MYSQL *mysql,const std::string& name="") { std::string sql_cmd = "select * from "; sql_cmd += TABLENAME; if(name.size()!=0) { sql_cmd += " where name='"; sql_cmd += name; sql_cmd += "'"; } sql_cmd += ";"; cout << "[INFO] " << sql_cmd << endl; int ret = mysql_query(mysql,sql_cmd.c_str()); if(ret!=0) { cerr << "[ERR] mysql query error: " << mysql_error(mysql) << endl; return ; } // 獲取結(jié)果 MYSQL_RES *res = mysql_store_result(mysql); if (res == nullptr) { cerr << "[ERR] mysql store_result error: " << mysql_error(mysql) << endl; return ; } int row = mysql_num_rows(res); // 行 int col = mysql_num_fields(res); //列 printf("%10s%10s%10s%10s\n", "ID", "姓名", "年齡", "成績"); for (int i = 0; i < row; i++) { MYSQL_ROW row_data = mysql_fetch_row(res); for (int i = 0; i < col; i++) { printf("%10s", row_data[i]); } printf("\n"); } // 釋放結(jié)果 mysql_free_result(res); }
get_all_in_stu(mysql);
執(zhí)行結(jié)果如下,顯示出了表中所有的值
[INFO] connect to 127.0.0.1:3306 root hello [INFO] mysql database connect success! [INFO] select * from stu_test; ID 姓名 年齡 成績 2 小圖圖 5 72.80 3 大司馬 42 87.30 4 樂迪 32 99.00
傳入特定名字,則只返回改名字所有值
get_all_in_stu(mysql,"樂迪");
[INFO] select * from stu_test where name='樂迪'; ID 姓名 年齡 成績 4 樂迪 32 99.00
這樣便實現(xiàn)了查詢操作。
3.5.1 模糊匹配
除了使用name=
,還可以使用name like %名字%
這條語句進行模糊匹配,即不在乎名字前后的內(nèi)容,只要有包含名字的數(shù)據(jù),就篩選出來。
select * from %s where name like '%牛%';
這樣就能將名字里面包含牛的所有數(shù)據(jù)都篩選出來
3.5.2 查詢接口操作注意事項
因為查詢的返回值是一個字符串二維數(shù)組,并不能通過字段名字獲取到對應(yīng)字段的內(nèi)容。這要求程序猿知曉這個表中字段的順序,才能通過下標獲取到正確的字段對其進行處理。
因為cpp并不像python那樣支持可變變量類型,所以要想篩選出對應(yīng)類型的數(shù)據(jù),還需要我們自行調(diào)用對應(yīng)的函數(shù)進行數(shù)據(jù)的轉(zhuǎn)換。
比如用atoi
函數(shù)將字符串轉(zhuǎn)為整型。
總結(jié)
到此這篇關(guān)于C/C++代碼操作MySQL數(shù)據(jù)庫詳細步驟的文章就介紹到這了,更多相關(guān)C/C++操作數(shù)據(jù)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Pipes實現(xiàn)LeetCode(193.驗證電話號碼)
這篇文章主要介紹了Pipes實現(xiàn)LeetCode(193.驗證電話號碼),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08