目录
视图
这里的视图与事务中的读视图是两个不同的概念:视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。视图的数据变化会影响到基表,基表的数据变化也会影响到视图
创建视图
修改视图后对原表产生影响,修改原表会对视图产生影响
原表数据发生了改变
删除视图
总结:使用视图时注意以下几点:
- 与表一样,必须唯一命名(不能出现同名视图或表名);
- 创建视图数目无限制,但要考虑复杂查询创建为视图之后的性能影响;
- 视图不能添加索引,也不能有关联的触发器或者默认值;
- 视图可以提高安全性,必须具有足够的访问权限;(它能从原表中把私密数据(如密码去除)后展示,修改视图也要影响原表)
- order by 可以用在视图中,但是如果从该视图检索数据 select 中也含有 order by ,那么该视图中的 order by 将被覆盖(但版本不同不一定会受影响)
用户管理
与Linux一样:mysql也是要进行多用户进行管理,因为多用户使用存在着安全问题
用户数据保存在 mysql 库中
可能你在之前配置时mysql登录时root是无密码登录的,也就是: skip-grant-tables 模式,此时设置密码会报错,首次对表user 操作要先权限刷新才能设置/修改密码
创建用户后也是要刷新权限后另一个客户端才能用新用户进行登录
另一端登录成功
@后面跟着用户登录的环境,localhost 代表他只能在本地进行登录;% 代表他能够在任意环境下进行登录
用户觉得碍眼可以把他进行删除
此时另一端就登不上了
数据库权限
mysql提供了很多权限
登录root用户,给zzj用户emp的select权限
zzj用户就能看到scott数据库,但进入后只能看到emp
只能继续select操作
如果想要emp全部的权限,则root要这么干
此时zzj就能进行操作了
觉得zzj不能进行emp的如何操作,则可以把权限回收了
此时zzj连scott库都看不到了
语言访问
mysql是指令级别进行操作,而语言要想支持操作数据库,mysql就必须为我们提供各种库名与头文件,让我们在语言级别实现数据库的基本操作;如果之前在配置mysql时选择的是yum源配置mysql后通过yum源下载的mysql-community-server,那么就代表库也帮你下完了,不用你在进行去官网下载库在导进文件中了,但默认没给我们提供头文件这个需要自己下载mysql的devel文件
sudo yum install mysql-community-devel
下载完后第一件是就是写代码来验证环境是否配置成功了
#include<iostream>
#include<mysql/mysql.h>
using namespace std;
int main()
{
cout<<"mysql version: "<<mysql_get_client_info()<<endl;
return 0;
}
进行编译时要指明对应链接的库,因为第三方库g++默认是不会自己找到即使它存在
g++ test.cc -L/lib64/mysql -l mysqlclient
正确打印出mysql版本号就说明环境没问题
准备工作
使用root账号创建空数据库并给普通用户(未来登录时使用它进行登录)库的所有操作权
查看普通用户视角操作库
使用函数
先进行数据库对象mysql初始化,接着链接时要设置各种配置信息(用户名,密码,端口号...),使用后对mysql进行关闭
#include<iostream>
#include<string>
#include<unistd.h>
#include<mysql/mysql.h>
const std::string host="localhost";
const std::string user="zzj";
const std::string password="0628";
const std::string database="test_conn";
unsigned int port=3306;
int main()
{
//初始化
MYSQL *mq=mysql_init(nullptr);
if(mq==nullptr)
{
std::cerr<<"mysql init fail"<<std::endl;
return 1;
}
//远程链接数据库
MYSQL* my=mysql_real_connect(mq,host.c_str(),user.c_str(),
password.c_str(),database.c_str(),port,nullptr,0);
if(my==nullptr)
{
std::cerr<<"mysql connect fail"<<std::endl;
return 1;
}
//添加等待进行观察
sleep(10);
std::cout<<"sucess"<<std::endl;
//使用完后要关闭
mysql_close(mq);
return 0;
}
运行程序后,我们确实通过上层访问到了数据库
使用 mysql_query 函数将我们输入的字符串mysql语句在数据库内执行,就可以制作出一个简易版的mysql客户端
#include<iostream>
#include<string>
#include<unistd.h>
#include<mysql/mysql.h>
const std::string host="localhost";
const std::string user="zzj";
const std::string password="0628";
const std::string database="test_conn";
unsigned int port=3306;
int main()
{
//初始化
MYSQL *mq=mysql_init(nullptr);
if(mq==nullptr)
{
std::cerr<<"mysql init fail"<<std::endl;
return 1;
}
//远程链接数据库
MYSQL* my=mysql_real_connect(mq,host.c_str(),user.c_str(),
password.c_str(),database.c_str(),port,nullptr,0);
if(my==nullptr)
{
std::cerr<<"mysql connect fail"<<std::endl;
return 1;
}
std::string mysql;
while(true)
{
std::cout<<"Mysql> ";
std::getline(std::cin,mysql);
if(mysql=="quit" || mysql.empty())
{
std::cout<<"Bye"<<std::endl;
break;
}
mysql_query(my,mysql.c_str());
}
//使用完后要关闭
mysql_close(mq);
return 0;
}
我们输入在程序运行时输入的mysql语句成功地执行了
但在这里有一个问题:怎么中文输入的字符串出现了乱码? 之前在配置mysql时默认是utf-8 支持汉字啊;问题不在这里,而在建立链接后访问数据库时它默认使用字符集latin1去访问的,需要使用 mysql_set_character_set() 设置下字符串下即可
不用;语句也可以执行成功(函数默认只能执行一条语句,防止SQL注入);现在已经可以继续增删改操作了,查操作虽然也可以,但它执行结果后要给我们打印出数据信息才是我们要的;
边框可以打印,要的是属性名与下面对应的内容,要怎么实现呢?
先用 MYSQL_RES* mysql_store_result() 保存结果的所有数据,它是char**[] 数组;接着使用mysql_num_rows(MYSQL_RES *) 和 mysql_num_fields(MYSQL_RES *) 获取到行数与列数,注意传入的参数是前面的函数返回对象;获取总属性名使用 mysql_fetch_fields(MYSQL_RES *),它是 char*[]数组,打印时要根据列数才能打印完整;内容提供 mysql_fetch_row(MYSQL_RES *) 它也是char*[]数组,不过它只保存着第一行的内容,下次调用就返回第二行的内容...也是要根据行数与列数才能打印完整内容
#include<iostream>
#include<string>
#include<unistd.h>
#include<mysql/mysql.h>
const std::string host="localhost";
const std::string user="zzj";
const std::string password="0628";
const std::string database="test_conn";
unsigned int port=3306;
int main()
{
//初始化
MYSQL *mq=mysql_init(nullptr);
if(mq==nullptr)
{
std::cerr<<"mysql init fail"<<std::endl;
return 1;
}
//远程链接数据库
MYSQL* my=mysql_real_connect(mq,host.c_str(),user.c_str(),
password.c_str(),database.c_str(),port,nullptr,0);
if(my==nullptr)
{
std::cerr<<"mysql connect fail"<<std::endl;
return 1;
}
//设置utf-8字符集
mysql_set_character_set(mq,"utf8");
std::string mysql="select *from people";
mysql_query(my,mysql.c_str());
//获取结果的所有数据保存在MYSQL_RES对象中
MYSQL_RES* res=mysql_store_result(my);
//获取内容行和列(在MYSQL_RES中获取)
int rows=mysql_num_rows(res);
int fields=mysql_num_fields(res);
//打印属性.属性相关保存在MYSQL_FIELD对象中
MYSQL_FIELD *fields_at=mysql_fetch_fields(res);
for(int i=0;i<fields;i++)
{
std::cout<<fields_at[i].name<<' ';
}
std::cout<<std::endl;
//打印内容
for(int i=0;i<rows;i++)
{
//相等与迭代器:调用一次跳转到下一行
MYSQL_ROW row_content=mysql_fetch_row(res);
for(int j=0;j<fields;j++)
{
std::cout<<row_content[j]<<' ';
}
std::cout<<std::endl;
}
//使用完后是否结果集
mysql_free_result(res);
//使用完后要关闭
mysql_close(mq);
return 0;
}
程序运行结果
以上操作都是mysql为了支持C语言操作数据库提供的各种函数,像C++,Java也有自己的mysql库,需要查找文档后自行测试使用
mysql界面级工具
mysql也支持使用界面的方式来连接数据库进行使用,以Winodws为例,先到官网下载:Download MySQL Workbench;在数据库中准备一个用户,host设置为‘%’表示任何地方都能连接;还要在my.cnf配置中添加:
bind-address=0.0.0.0
skip-networking = OFF
下载完软件后,点击+填上对应的数据库用户信息
填写完再次点击填好的信息就登录进来了(但我这边给用户开通了全部权限,在本地数据库上可以修改数据,但在图像化界面里修改不了数据,是BUG?)
连接池
在正式的应用场景中,要怎么设计让使用者使用sql语句高效地在语言层面上执行呢?与前面数据的线程池类似:数据一个类,类中有线程和任务队列的成员变量,让每个线程先跑起来,把mysql对象初始化,等待任务到来;使用sql语句准备好后,把sql语句包装成任务队列中的对象:里面保存着sql语句字符串,相关执行的函数,标记位;任务到来后唤醒线程,让其中一个线程拿着一个任务执行mysql_query()函数;如果是select执行要返回处理结果后返回,就可以把方法绑定后传给线程,线程根据标记位执行回调函数后把处理完的数据给我们返回
以上便是全部内容,有问题欢迎在评论区指正,感谢观看!