我应该使用什么数据结构来对数据库/表进行建模

What data structure should I use to model a database/table?

本文关键字:建模 数据库 什么 数据结构 我应该      更新时间:2023-10-16

数据库通常如下所示

┃Name|Age|..┃
┠────┼───┼──┨
┃John│025│..┃
┃Carl│033│..┃
┃....│...│..┃

在这种情况下,我指的是一个具有固定列大小和可变大小的未排序行的表,这些行可以由id寻址。

C++11(或更早版本)中是否有数据结构可以表示这样的数据?

我想了几种欺骗这种结构的方法,但没有一种是完美的。

1.分离std::vector

std::vector<std::string> name;
std::vector<unsigned int> age;
// Write
name.push_back("John");
age.push_back(25);
// Read
std::cout << "The first entry is (" << name[0] << " | " << age[0] << ")n";

然而,定义一个有很多列的表需要大量的标记,并且通过在每个std::vector上调用push_back来写入它真的很乏味。

2.std::tuple中的std::vector

(在这种情况下std::pair就足够了)

std::vector<std::tuple<std::string, unsigned int>> table;
// Write
table.push_back(std::make_tuple("John", 25));
// Read 1
std::string name;
unsigned int age;
std::tie(name, age) = table[0];
std::cout << "The first entry is (" << name << " | " << age << ")n";
// Read 2
enum
{
NAME = 0,
AGE
}
std::cout << "The first entry is (" << std::get<NAME>(table[0]) << " | "
<< std::get<AGE>(table[0]) << ")n";

(对不起,如果我把这里搞砸了;从昨天起我就知道std::tuple的存在)

这很好,但这一次,当你必须定义要放入值的新变量时,从中读取需要大量标记。你可以对任何需要值的变量执行std::tie,但这会变得不可读。第二种方法几乎是完美的,但我不想在C++11中使用隐式枚举。

3.std::array中的std::vector

enum
{
NAME = 0,
AGE
}
std::vector<std::array<std::string, 2> table;
// Write
table.push_back({"John", "25"});
// Read
std::cout << "The first entry is (" << table[0][NAME] << " | " << table[0][AGE] << ")n";

这也很好,但它遇到了与2.2相同的问题。此外,这只允许std::string值。作为交换,它提供了更短更好的语法。

我建议使用std::vector<Record>来保存您的记录。

使用std::map<key, vector_index>作为记录的索引。这将使您能够按不同的搜索条件访问记录,而无需一直对矢量进行排序。

您没有考虑使用某种关联数组的std::vector,无论是std::map还是std::unordered_map

这将允许您使用数据库列名检查矢量(或其他顺序容器)中的给定项目

item["Name"]
item["Age"]

等等。很明显,你必须使用一个变体或类似boost::any的东西来表示这个值。

如果你想用C++与数据库对话,并在编译时知道列的类型(正如你从建议中看到的那样),那么可能值得考虑直接从数据库模式中为你生成具有适当结构的代码的方法。这里和这里已经有几个关于这个主题的问题了。如果db值为null怎么办?

由于这个问题在5年后仍然存在,我将用5年的编程经验亲自回答。

使用std::arraystd::tuple来表示一行是没有意义的。结构更具表现力,样板更少。

这个问题主要询问AOS(结构数组)、SOA(数组结构)和散列映射之间的区别。两者之间的选择取决于你想对数据做什么以及有多少数据

当迭代数据时,通过自动缓存预加载来加载64字节的数据缓存行。由于哈希映射是不连续的,因此不能利用缓存机制,因此只有当基于单个条目的密钥访问它们时,而不是在整个数据集上迭代时,才应该首选哈希映射。

AOS和SOA之间的选择取决于列是单独迭代还是一起迭代。当单独迭代时,通过使用SOA,我们可以在缓存线上放置更多相同的数据,而不必查看其他数组。对于AOS和SOA,优选的数据结构是std::vector,它是一个简单的连续数据结构,因此处理器有很多信息用于动态优化。

#-------------------------------------------
#Try with this piece of code based on <map>
#-------------------------------------------    
#include <iostream>
#include <map>
using namespace std;
//---
class myBook
{
public:
string ISBN;
string Title;
int Pages;
myBook();
myBook(const myBook &);
~myBook(){};
myBook &operator=(const myBook &pTr);
int operator==(const myBook &pTr) const;
int operator<(const myBook &pTr) const;
};
myBook::myBook()
{
ISBN = "";
Title = "";
Pages = 0;
}

myBook::myBook(const myBook &copyin)
{
ISBN = copyin.ISBN;
Title = copyin.Title;
Pages = copyin.Pages;
}

ostream &operator<<(ostream &output, const myBook &myBook)
{
output << myBook.ISBN << ':' << myBook.Title << ':' << myBook.Pages << std::endl;
return(output);
}

myBook& myBook::operator=(const myBook &pTr)
{
this->ISBN = pTr.ISBN;
this->Title = pTr.Title;
this->Pages = pTr.Pages;
return(*this);
}

int myBook::operator==(const myBook &pTr) const
{
if( this->ISBN != pTr.ISBN) return(0);
if( this->Title != pTr.Title) return(0);
if( this->Pages != pTr.Pages) return(0);
return(1);
}
//---------------------------
main()
{
map<string, myBook> BooksLibrary;
myBook book1;
//---
book1.ISBN="1243954-23";
book1.Title="Autobiography by Ben Franklin";
book1.Pages=432;
BooksLibrary["0001"] = book1;
//---
book1.ISBN="555-USA991";
book1.Title="I Robot by Isac Asimov";
book1.Pages=323;
BooksLibrary["0002"] = book1;
//---
for( map<string, myBook>::iterator ii=BooksLibrary.begin();     ii!=BooksLibrary.end(); ii++)
{
std::cout << (*ii).first << "|" << (*ii).second << endl;
}
//---
return(0);
}