视图
视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。视图的数据变化会影响到基表,基表的数据变化也会影响到视图。
基本使用
创建视图:
create view 视图名 as select语句;
其实就相当于将要查询的列形成一个新的表;
并且修改了视图,对基表数据有影响:
修改了基表,对视图有影响:
删除视图:
drop view 视图名;
视图在实际当中用的不多。
视图规则和限制
与表一样,必须唯一命名(不能出现同名视图或表名)。
创建视图数目无限制,但要考虑复杂查询创建为视图之后的性能影响。
视图不能添加索引,也不能有关联的触发器或者默认值。
视图可以提高安全性,必须具有足够的访问权限。
order by 可以用在视图中,但是如果从该视图检索数据 select 中也含有 order by ,那么该视图中的 order by 将被覆盖。
视图可以和表一起使用。
用户管理
如果我们只能使用root用户,这样存在安全隐患。这时,就需要使用MySQL的用户管理。
用户
用户信息
MySQL中的用户,都存储在系统数据库mysql的user表中。
字段解释:
host: 表示这个用户可以从哪个主机登陆,如果是localhost,表示只能从本机登陆
user: 用户名
authentication_string: 用户密码通过password函数加密后的
*_priv: 用户拥有的权限
基础操作
创建用户
create user ‘用户名’@‘登陆主机/ip’ identified by ‘密码’;
@后面如果是%,说明可以进行任意地点登录,允许远端登录,本地登录。
删除用户
drop user ‘用户名’@‘主机名’
修改用户密码
自己改自己密码:
set password=password(‘新的密码’);
root用户修改指定用户的密码:
set password for ‘用户名’@‘主机名’=password(‘新的密码’);
数据库的权限
首先了解flush:
FLUSH命令用于管理服务器内部状态,包括清除缓存、重新加载配置或刷新日志等,确保操作生效。其常见用途及示例如下:
清除缓存/缓冲区:释放内存中的临时数据,避免过时信息影响查询。
重新加载配置:使某些配置更改立即生效,无需重启服务。
维护日志文件:安全切换日志文件,便于备份或归档。
MySQL数据库提供的权限列表:
权限 | 列 | 上下文 |
---|---|---|
CREATE | Create_priv | 数据库、表或索引 |
DROP | Drop_priv | 数据库或表 |
GRANT OPTION | Grant_priv | 数据库、表或保存的程序 |
REFERENCES | References_priv | 数据库或表 |
ALTER | Alter_priv | 表 |
DELETE | Delete_priv | 表 |
INDEX | Index_priv | 表 |
INSERT | Insert_priv | 表 |
SELECT | Select_priv | 表 |
UPDATE | Update_priv | 表 |
CREATE VIEW | reate_view_priv | 视图 |
SHOW VIEW | Show_view_priv | 视图 |
ALTER ROUTINE | Alter_routine_priv | 保存的程序 |
CREATE ROUTINE | Create_routine_priv | 保存的程序 |
EXECUTE | Execute_priv | 保存的程序 |
EILE | File_priv | 服务器主机上的文件访问 |
CREATE TEMPORARY TABLES | Create_tmp_table_priv | 服务器管理 |
LOCK TABLES | Lock_tables_priv | 服务器管理 |
CREATE USER | Create_user_priv | 服务器管理 |
PROCESS | Process_priv | 服务器管理 |
RELOAD | Reload_priv | 服务器管理 |
REPLICATION CLIENT | Repl_client_priv | 服务器管理 |
REPLICATION SLAVE | Repl_slave_priv | 服务器管理 |
SHOW DATABASES | Show_db_priv | 服务器管理 |
SHUTDOWN | Shutdown_priv | 服务器管理 |
SUPER | Super_priv | 服务器管理 |
给用户授权
刚创建的用户没有任何权限。需要给用户授权。
grant 权限列表 on 库.对象名 to ‘用户名’@‘登陆位置’ [identified by ‘密码’]
权限列表,多个权限用逗号分开:
grant select on …
grant select, delete, create on …
grant all [privileges] on … – 表示赋予该用户在该对象上的所有权限
*. : 代表本系统中的所有数据库的所有对象(表,视图,存储过程等)
库. : 表示某个数据库中的所有数据对象(表,视图,存储过程等)
identified by可选。 如果用户存在,赋予权限的同时修改密码,如果该用户不存在,就是创建用户
左侧是ROOT用户,右侧是新创建的mfc用户,发现mfc用户只能查看到一个表,这是因为mfc没有权限查看ROOT用户创建的表。
给予权限之后就可以看到对应的数据库了。
特定用户现有查看权限
show grants for ‘用户名’@‘%’;
回收权限
revoke 权限列表 on 库.对象名 from ‘用户名’@‘登陆位置’;
C/C++进行MySQL链接
首先先创建一个链接专属的账户:
尽量不要用@’%‘。
创建一个专属的数据库并且给予权限。
Connector/C 使用
其中 include 包含所有的方法声明, lib 包含所有的方法实现(打包成库)
尝试链接mysql client
通过 mysql_get_client_info() 函数,来验证我们的引入是否成功
#include <stdio.h>
#include <mysql/mysql.h>
int main()
{
printf("mysql client Version: %s\n", mysql_get_client_info());
return 0;
}
这里证明将库引入了。
mysql接口介绍
初始化mysql_init()
要使用库,必须先进行初始化!
MYSQL *mysql_init(MYSQL *mysql)
这里和文件一样,要记得关闭
链接数据库mysql_real_connect
初始化完毕之后,必须先链接数据库,在进行后续操作。(mysql网络部分是基于TCP/IP的)
MYSQL *mysql_real_connect(MYSQL *mysql,//初始化的返回值
const char *host,//主机IP
const char *user,//账户
const char *passwd,//密码
const char *db,//要连接哪个数据库
unsigned int port,//数据库端口号
const char *unix_socket,//Unix socket 路径(若为 NULL 则使用默认值)
unsigned long client_flag)// 客户端连接标志(通常为 0)
//建立好链接之后,获取英文没有问题,如果获取中文是乱码:
//设置链接的默认字符集是utf8,原始默认是latin1
mysql_set_character_set(myfd, "utf8");
第一个参数 MYSQL是 C api中一个非常重要的变量(mysql_init的返回值),里面内存非常丰富,有port,dbname,charset等连接基本参数。它也包含了一个叫 st_mysql_methods的结构体变量,该变量里面保存着很多函数指针,这些函数指针将会在数据库连接成功以后的各种数据操作中被调用。mysql_real_connect函数中各参数,基本都是顾名思意。
#include <iostream>
#include <mysql/mysql.h>
#include <string>
using namespace std;
const string host = "127.0.0.1";
const string user = "connect";
const string passwd = "bossaa1s";
const string db = "connect";
const unsigned int port = 3306;
int main()
{
//printf("mysql client Version: %s\n", mysql_get_client_info());
MYSQL *my = mysql_init(nullptr);
if(my == 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,NULL,0) == nullptr)
{
cerr << "connect MYSQL error" <<endl;
return 2;
}
mysql_set_character_set(my, "utf8");
cout << "connect success" <<endl;
mysql_close(my);
return 0;
}
这里记得要启动mysql的服务器才能启动成功。
下发mysql命令mysql_query
int mysql_query(MYSQL *mysql, const char *q);
第二个参数为要执行的sql语句,如“select * from table”。
先创建一个表:
然后可以通过这个方式查询连接数据库的信息和状态:
然后让刚才的程序sleep十秒钟。
红框是我们C++的方式连接的数据库,蓝色框是sleep运行的时间。
然后进入正题:
#include <iostream>
#include <mysql/mysql.h>
#include <string>
#include <unistd.h>
using namespace std;
const string host = "127.0.0.1";
const string user = "connect";
const string passwd = "bossaa1s";
const string db = "connect";
const unsigned int port = 3306;
int main()
{
//printf("mysql client Version: %s\n", mysql_get_client_info());
MYSQL *my = mysql_init(nullptr);
if(my == 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,NULL,0) == nullptr)
{
cerr << "connect MYSQL error" <<endl;
return 2;
}
mysql_set_character_set(my, "utf8");
string sql;
while(1)
{
cout << "MySQL>>>";
if(!getline(cin,sql)|| sql == "quit")
{
cout << "bye bye" <<endl;
break;
}
int n = mysql_query(my,sql.c_str());
if(n == 0) cout << sql << "success:" << n << endl;
else cerr << mysql_error(my) << endl;
}
cout << "connect success" <<endl;
mysql_close(my);
return 0;
}
而且这里的命令行其实可以不用带分号结尾的。
这里的插入增删改不必担心,因为有事务的存在,保证了原子性和回滚。
但是select * from table语句就有一些细节了,这个后面再说。
获取执行结果mysql_store_result
sql执行完以后,如果是查询语句,我们当然还要读取数据,如果update,insert等语句,那么就看下操作成功与否即可。我们来看看如何获取查询结果: 如果mysql_query返回成功,那么我们就通过mysql_store_result这个函数来读取结果。原型如下:
MYSQL_RES *mysql_store_result(MYSQL *mysql);
该函数会调用MYSQL变量中的st_mysql_methods中的 read_rows 函数指针来获取查询的结果。同时该函数会返回MYSQL_RES 这样一个变量,该变量主要用于保存查询的结果。同时该函数malloc了一片内存空间来存储查询过来的数据,所以我们一定要记的 free(result),不然是肯定会造成内存泄漏的。 执行完mysql_store_result以后,其实数据都已经在MYSQL_RES 变量中了,下面的api基本就是读取MYSQL_RES 中的数据。
那么这个结构究竟细节是什么呢?
首先清楚,这是从MYSQL转储到MYSQL_RES中的,我们拿到的每一行每一列数据都要有对应的空间进行存储。(mysql读取出来的数据全都当成字符串)
其实MYSQL_RES就是一个类似二级指针数组一样。
那么怎么去拿取到这个结构体当中的结果呢?
获取结果行数mysql_num_rows
my_ulonglong mysql_num_rows(MYSQL_RES *res);
获取结果列数mysql_num_fields
unsigned int mysql_num_fields(MYSQL_RES *res);
#include <iostream>
#include <mysql/mysql.h>
#include <string>
#include <unistd.h>
using namespace std;
const string host = "127.0.0.1";
const string user = "connect";
const string passwd = "bossaa1s";
const string db = "connect";
const unsigned int port = 3306;
int main()
{
MYSQL *my = mysql_init(nullptr);
if(my == 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,NULL,0) == nullptr)
{
cerr << "connect MYSQL error" <<endl;
return 2;
}
mysql_set_character_set(my, "utf8");
string sql = "select * from user";
int n = mysql_query(my,sql.c_str());
if(n == 0) cout << sql << "success:" << n << endl;
else
{
cerr << mysql_error(my) << endl;
return 3;
}
MYSQL_RES * res = mysql_store_result(my);
if(res == nullptr)
{
cerr << "mysql_store_result error" <<endl;
return 4;
}
my_ulonglong rows = mysql_num_rows(res);//获取行
unsigned int fields = mysql_num_fields(res);//获取列
cout << "行" << rows << endl;
cout << "列" << fields << endl;
cout << "connect success" <<endl;
mysql_close(my);
return 0;
}
获取列名mysql_fetch_fields
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res);
获取结果内容mysql_fetch_row
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
#include <iostream>
#include <mysql/mysql.h>
#include <string>
#include <unistd.h>
using namespace std;
const string host = "127.0.0.1";
const string user = "connect";
const string passwd = "bossaa1s";
const string db = "connect";
const unsigned int port = 3306;
int main()
{
MYSQL *my = mysql_init(nullptr);
if(my == 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,NULL,0) == nullptr)
{
cerr << "connect MYSQL error" <<endl;
return 2;
}
mysql_set_character_set(my, "utf8");
string sql = "select * from user";
int n = mysql_query(my,sql.c_str());
if(n == 0) cout << sql << "success:" << n << endl;
else
{
cerr << mysql_error(my) << endl;
return 3;
}
MYSQL_RES * res = mysql_store_result(my);
if(res == nullptr)
{
cerr << "mysql_store_result error" <<endl;
return 4;
}
my_ulonglong rows = mysql_num_rows(res);//获取行
unsigned int fields = mysql_num_fields(res);//获取列
cout << "行" << rows << endl;
cout << "列" << fields << endl;
//属性
MYSQL_FIELD *fields_array = mysql_fetch_fields(res);
for(int i = 0;i < fields;i++)
{
cout << fields_array[i].name <<"\t";
}
cout <<endl;
//内容
for(int i = 0;i < rows;i++)
{
MYSQL_ROW row = mysql_fetch_row(res);
for(int j = 0;j < fields;j++)
{
cout << row[j] << "\t";//*(row+j)
}
cout << endl;
}
cout << "connect success" <<endl;
mysql_close(my);
return 0;
}