引言
MariaDB 是一款灰常不错开源数据库. 这里直接用它来解决业务问题.
业务需求:
现在数据库中表示按照天分表的. 突然我们需要按照月来处理数据.
例如输入一个玩家id, 查找这个玩家这个月内看了一件事几次. 我们先搭建一个环境.
操作系统:
1
2
3
|
Linux version 4.4.0-22-generic (buildd@lgw01-41)
(gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2) )
#40-Ubuntu SMP Thu May 12 22:03:46 UTC 2016
|
首先安装 MariaDB数据库
1
2
3
4
5
|
sudo apt- get install mariadb-client
sudo apt- get install libmariadb2
sudo apt- get install libmariadb-client-lgpl-dev
sudo apt- get install libreoffice-mysql-connector
|
后面是C访问 MariaDB驱动. 这里扯一点, 目前关于MariaDB不懂问题, 搜不见直接当成mysql开始搜.
MariaDB安装成功后默认是开启的, 看下面图描述
后面搭建测试环境 首先 看 oss_musicelves.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
-- MySQL dump 10.10
--
-- Host: localhost Database: oss_log
-- ------------------------------------------------------
-- Server version 5.5.24-tmysql-1.4
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE= '+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE= 'NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `oss_musicelves`
--
DROP TABLE IF EXISTS `oss_musicelves`;
CREATE TABLE `oss_musicelves` (
`record_id` bigint (20) NOT NULL AUTO_INCREMENT,
`account_id` bigint (20) NOT NULL ,
`server_id` int (11) NOT NULL ,
`char_id` bigint (20) NOT NULL ,
`char_sex` int (11) NOT NULL ,
`type_id` int (11) NOT NULL ,
` timeStamp ` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' ,
`ptype` int (11) NOT NULL ,
`specifytype` int (11) NOT NULL ,
`childtype` int (11) NOT NULL ,
PRIMARY KEY (`record_id`),
KEY `idx_specifytype` (`specifytype`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `oss_musicelves`
--
/*!40000 ALTER TABLE `oss_musicelves` DISABLE KEYS */;
LOCK TABLES `oss_musicelves` WRITE;
INSERT INTO `oss_musicelves` VALUES (1,411948833,84869352,27899597414400801,0,1812, '2016-05-31 14:27:41' ,0,1,1),(2,1344702709,90964200,30422720614402293,0,1812, '2016-05-31 14:58:26' ,0,1,1),(3,706409913,90964200,30422720614401465,1,1812, '2016-05-31 14:58:27' ,0,1,2),(4,706409913,392964857,30422720614401465,1,1812, '2016-05-31 14:58:59' ,0,2,4),(5,1344702709,392964857,30422720614402293,0,1812, '2016-05-31 14:58:59' ,0,2,4),(6,706409913,90964200,30422720614401465,1,1812, '2016-05-31 15:04:52' ,0,1,2),(7,706409913,392964857,30422720614401465,1,1812, '2016-05-31 15:05:54' ,0,2,4),(8,1344702709,392964857,30422720614402293,0,1812, '2016-05-31 15:05:54' ,0,2,4),(9,1344702709,90964200,30422720614402293,0,1812, '2016-05-31 15:10:29' ,0,1,1),(10,706409913,90964200,30422720614401465,1,1812, '2016-05-31 15:10:32' ,0,1,2),(11,1344702709,392964857,30422720614402293,0,1812, '2016-05-31 15:10:54' ,0,2,4),(12,3145910262,90964200,29520779366416374,1,1812, '2016-05-31 15:30:00' ,0,1,1),(13,1372825842,90964200,30173879500803314,1,1812, '2016-05-31 15:30:01' ,0,1,2),(14,3145910262,392964857,29520779366416374,1,1812, '2016-05-31 15:30:04' ,0,2,4),(15,1372825842,392964857,30173879500803314,1,1812, '2016-05-31 15:30:04' ,0,2,4),(16,3145910262,392964857,29520779366416374,1,1812, '2016-05-31 15:34:24' ,0,2,4),(17,1372825842,392964857,30173879500803314,1,1812, '2016-05-31 15:34:24' ,0,2,4),(18,706409913,90964200,30422720614401465,1,1812, '2016-05-31 15:40:14' ,0,1,1),(19,1344702709,90964200,30422720614402293,0,1812, '2016-05-31 15:40:16' ,0,1,2),(20,3145910262,392964857,29520779366416374,1,1812, '2016-05-31 15:42:19' ,0,2,4),(21,1372825842,392964857,30173879500803314,1,1812, '2016-05-31 15:42:19' ,0,2,4),(22,1027763684,90964200,30175730790400484,0,1812, '2016-05-31 16:56:33' ,1,1,1),(23,1372825842,90964200,30173879500803314,1,1812, '2016-05-31 16:56:50' ,0,1,2),(24,1372825842,392964857,30173879500803314,1,1812, '2016-05-31 16:57:37' ,0,2,3),(25,1027763684,392964857,30175730790400484,0,1812, '2016-05-31 16:57:37' ,1,2,3),(26,1372825842,392964857,30173879500803314,1,1812, '2016-05-31 17:04:33' ,0,2,3),(27,1027763684,392964857,30175730790400484,0,1812, '2016-05-31 17:04:33' ,1,2,3),(28,1027763684,90964200,30175730790400484,0,1812, '2016-05-31 17:14:15' ,1,1,2),(29,1372825842,392964857,30173879500803314,1,1812, '2016-05-31 17:14:50' ,0,2,3),(30,1027763684,392964857,30175730790400484,0,1812, '2016-05-31 17:14:50' ,1,2,3),(31,751699770,90964200,30175199027201850,1,1812, '2016-05-31 18:14:59' ,1,1,1);
UNLOCK TABLES;
/*!40000 ALTER TABLE `oss_musicelves` ENABLE KEYS */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
这个 oss_musicelves.sql 文件主要功能是创建 oss_musicelves数据库, 并填充数据.
还有一个 搭建环境 的 脚本 mariadb_test.sql 和上一个sql文件放在同一个目录下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# 创建一个测试数据库
create database oss_log;
# 进入oss_log 数据库
use oss_log;
# 创建 oss_musicelves 数据库, 并导入数据
source oss_musicelves.sql;
# 批量创建表和数据
create table 2016_6_1_oss_musicelves select * from oss_musicelves;
create table 2016_6_2_oss_musicelves select * from oss_musicelves;
create table 2016_6_3_oss_musicelves select * from oss_musicelves;
create table 2016_6_4_oss_musicelves select * from oss_musicelves;
create table 2016_6_5_oss_musicelves select * from oss_musicelves;
create table 2016_6_9_oss_musicelves select * from oss_musicelves;
create table 2016_6_10_oss_musicelves select * from oss_musicelves;
create table 2016_6_12_oss_musicelves select * from oss_musicelves;
# 查询表是否创建成功
show tables;
# 这里处理 拿到的数据
select distinct table_name from information_schema.columns where table_name like '2016_6_%_oss_musicelves' ;
|
直接放在 MariaDB控制台中直接刷进去. 搭建的具体环境如下
到这里环境基本搭建好了. MariaDB入门等等, 完全可以当做mysql 学习温故一遍.
前言
上面问题就是 原本 是 select * from oss_musicelves; 就可以解决的问题.
这里 需要 输入年和月 外加一些特殊条件 . select * from %_%_%_oss_musicelves; 解决. 单纯用sql脚本也可以解决.非常复杂.用的不熟.
这里首先通过 shell 脚本处理
1
2
3
|
touch getmouths.sh
chmod +x getmouths.sh
vi getmouths.sh
|
具体的脚本 内容 如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
#!/bin/sh
#得到输入的玩家ptid
if [ $# -lt 1 ]
then
echo "uage: $0 [ptid]"
exit -1
fi
ptid=$1
mouth=$( date +%m | sed s '/^0//' )
#第一个参数是月份
if [ $# -ge 2 ]
then
mouth=$2
fi
#第二个参数是年
year =$( date +%Y)
if [ $# -ge 3 ]
then
year =$3
fi
#得到查询的随机表名
tbname= "\"${year}_${mouth}_%_oss_musicelves\""
#这里得到mysql 中所有合法表名
rm -rf __tmp
touch __tmp
#开始查询数据库了, 需要以root权限启动这个脚本
mysql -e "select distinct table_name from information_schema.columns where table_name like $tbname" | awk 'NR>1' | while read name
do
mysql -e "select count(*) from oss_log.$name where specifytype = 1 and char_id = $ptid" | awk 'NR>1' | while read cut
do
echo "$name : $cut"
echo $cut >> __tmp
break
done
done
#统计表里面的数据
sum =$(cat __tmp | awk '{s+=$1} END {print s}' )
rm -rf __tmp
# 最后输出统计结果
echo "$year-$mouth sum: $sum"
|
使用脚本 截图
通过shell可以完成 我们的需求. Linux上shell真好用. window的bat不好用.
正文
第一部分 : 让C调用MariaDB跑通
先看 测试Demo mariadb_demo.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#include <stdio.h>
#include <stdlib.h>
#include <mysql.h>
/*
* 第一个 mariadb程序
*/
int main( int argc, char *argv[]) {
// 创建数据连接对象
MYSQL *con = mysql_init( NULL );
if (con == NULL ) {
fprintf(stderr, "%s\n" , mysql_error(con));
exit(EXIT_FAILURE);
}
if (!mysql_real_connect(con, "localhost" , "root" , "" , NULL , 0, NULL , 0)) {
fprintf(stderr, "%s\n" , mysql_error(con));
mysql_close(con);
exit(EXIT_FAILURE);
}
if (mysql_query(con, "show databases;" )) {
fprintf(stderr, "%s\n" , mysql_error(con));
mysql_close(con);
exit(EXIT_FAILURE);
}
puts( "mariadb is connect and run succesed!" );
mysql_close(con);
return 0;
}
|
具体的编译 命令
1
2
3
|
su root
gcc -Wall -ggdb2 -I/usr/include/mariadb -o mariadb_demo. out mariadb_demo.c -lmysqlclient
./mariadb_demo. out
|
运行结果 如下
到这里基本C 调用 MariaDB 基本流程跑通了. 但是很不爽. 只能通过root用户使用.
那我们改变这里不爽. 进入第二部分. 扩展资料 c in mariadb http://*.com/questions/17265471/using-mariadb-in-c
第二部分 : 通过普通用户完成业务需求.
先创建普通用户 csz, 密码是 1413222, 并并且给其 select 读权限
1
2
3
4
5
6
7
8
|
su root
mysql
drop user csz;
create user 'csz' @ '%' identified by '13142222' ;
grant select on *.* to 'csz' @ '%' ;
# 立即刷新
flush privileges;
|
后面登录试试
mysql -ucsz -p1314222 -h127.0.0.1
主要是mariadb默认关闭远程访问. 后面我们开启安全访问模式试试
su root/etc/init.d/mysql stopmysqld_safe --skip-grant-tables
后面再开启一个会话 . 重新输入 mysql -ucsz -p1314222 -h127.0.0.1 , 解决可以了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#目标拼接 串内容
select sum (c) from (
select count (*) as c from 2016_6_1_oss_musicelves where specifytype=1 and char_id = 30422720614402293
union all
select count (*) from 2016_6_2_oss_musicelves where specifytype=1 and char_id = 30422720614402293
union all
select count (*) from 2016_6_3_oss_musicelves where specifytype=1 and char_id = 30422720614402293
union all
select count (*) from 2016_6_4_oss_musicelves where specifytype=1 and char_id = 30422720614402293
union all
select count (*) from 2016_6_5_oss_musicelves where specifytype=1 and char_id = 30422720614402293
union all
select count (*) from 2016_6_9_oss_musicelves where specifytype=1 and char_id = 30422720614402293
union all
select count (*) from 2016_6_10_oss_musicelves where specifytype=1 and char_id = 30422720614402293
union all
select count (*) from 2016_6_12_oss_musicelves where specifytype=1 and char_id = 30422720614402293
) as t;
|
具体看 getmouths.c 文件 内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
#include <stdio.h>
#include <stdlib.h>
#include < time .h>
#include <mysql.h>
#define _INT_BUF (4098)
// 得到查询数据表内容
#define _STR_SQLTABLES \
"select distinct table_name from information_schema.columns where table_name like '%d_%d_%%_oss_musicelves'"
#define _STR_SQLSELECT \
"select count(*) as c from %s where specifytype=1 and char_id = %lld"
// 基础的mariadb 错误关闭函数
static inline void _err_mariadb(MYSQL *con) {
fprintf(stderr, "_err_mariadb error: %s\n" , mysql_error(con));
mysql_close(con);
exit(EXIT_FAILURE);
}
/*
* 处理 oss_musicelves 一个月的所有表.
*/
int main( int argc, char * argv[]) {
long long ptid;
time_t rt = time ( NULL );
struct tm *pt = localtime(&rt);
int year = pt->tm_year + 1900;
int mouth = pt->tm_mon + 1;
// 先简单检测输入
if(argc <= 1) {
fprintf(stderr, "%s [ptid] [mouth] [year]\n" , argv[0]);
exit(EXIT_FAILURE);
}
// 先得到 ptid 数据
ptid = atoll(argv[1]);
// 得到当前月份
if(argc >= 3)
mouth = atoi(argv[2]);
// 得到当前年份
if(argc >= 4)
year = atoi(argv[3]);
// 简单检测结果是否合法
if(ptid < 0 || mouth <=0 || mouth>12 || year <1900) {
fprintf(stderr, "%s %lld %d %d is error!\n" , argv[0], ptid, mouth, year );
exit(EXIT_FAILURE);
}
// 输出结果
printf( "%s %lld %d %d start run!\n" , argv[0], ptid, mouth, year );
// 开始用mysql 访问我们需要访问的数据结果了
MYSQL *con = mysql_init( NULL );
if(con == NULL ) {
fprintf(stderr, "mysql_init error: %s\n" , mysql_error(con));
exit(EXIT_FAILURE);
}
if(!mysql_real_connect(con, "127.0.0.1" , "csz" , "1314222" , "oss_log" , 0, NULL , 0))
_err_mariadb(con);
char sqls[_INT_BUF];
int sqlen = 0;
sprintf(sqls, _STR_SQLTABLES, year , mouth);
if(mysql_query(con, sqls))
_err_mariadb(con);
// 开始得到结果
MYSQL_RES *ret = mysql_store_result(con);
if( NULL == ret)
_err_mariadb(con);
MYSQL_ROW row;
int i = 0, nr = 0;
while(!!(row = mysql_fetch_row(ret))) {
if(i == 0) {
sqlen = sprintf(sqls, "select sum(c) from (\n" _STR_SQLSELECT, row[0], ptid);
i = 1;
continue ;
}
// 后面正常拼接
nr = sprintf(sqls + sqlen, "\nunion all\n" _STR_SQLSELECT, row[0], ptid);
if((sqlen += nr) >= _INT_BUF) {
fprintf(stderr, "sprintf while %d too length.\n" , sqlen);
goto __return_free;
}
}
if(i == 0) {
printf( "sum %lld %d/%d: 0\n" , ptid, year , mouth);
goto __return_free;
}
// 这里处理有的数据
nr = sprintf(sqls + sqlen, "\n) as t;" );
if((sqlen += nr) >= _INT_BUF) {
fprintf(stderr, "sprintf end %d too length.\n" , sqlen);
goto __return_free;
}
// 内存用完了就直接释放
mysql_free_result(ret);
ret = NULL ;
printf( "sql : \n\t%s\n" , sqls);
// 开始输出统计结果
if(mysql_query(con, sqls))
_err_mariadb(con);
if((ret = mysql_store_result(con))== NULL )
_err_mariadb(con);
//得到结果直接返回
if(!!(row=mysql_fetch_row(ret)))
printf( "sum %lld %d/%d: %s\n" , ptid, year , mouth, row[0]);
else
puts( "select is empty!" );
__return_free:
// 释放用过的内存
mysql_free_result(ret);
// 关闭打开的 数据库访问对象
mysql_close(con);
return 0;
}
|
编译命令
gcc -Wall -ggdb2 -I/usr/include/mariadb -o getmouths.out getmouths.c -lmysqlclient
最终运行结果是
如果想详细了解关于mariadb c驱动的api使用, 可以参照老外写的很好理解.
mysqlc demo http://zetcode.com/db/mysqlc/
到这里就结束了, 关于C 访问数据库能力也基本打通了.
后记
错误是难免, 欢迎学习进步~~~ 未来什么都不确定, 可以确定是没有未来, 只有现在还在装逼 .
以上这篇C基础 mariadb处理的简单实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。