在数据库中保存动态列表的首选方法是什么?

时间:2010-09-11 14:56:26

标签: sql database database-design

在我们的应用程序中,用户可以创建不同的列表(例如sharepoint),例如用户可以创建汽车列表(名称,型号,品牌)和学生列表(姓名,dob,地址,国籍)等

我们的应用程序应该能够查询列表的不同列,这样我们就不能只序列化每一行并将其保存在一行中。

我应该在运行时为每个新创建的列表创建一个新表吗?如果这是最好的解决方案,那么我认为可能Microsoft SharePoint也会做到这一点?

我应该使用以下架构

Lists (Id, Name)
ListColumns (Id, ListId, Name)
ListRows (Id, ListId)
ListData(RowId, ColumnId, Value)

虽然单行会在列表数据表中创建与列表中的列一样多的行,但这感觉不对。

你有没有处理过这种情况?你是如何在数据库中处理它的?

5 个答案:

答案 0 :(得分:3)

你做的是EAV (Entity-Attribute-Value Model)

对于包含3列和1000个条目的列表:

列表中的1条记录 ListColumns中的3条记录 ListData中的3000个条目和

中的3000个条目

这很好。我不是动态创建表的粉丝,因为它可能会弄乱你的数据库,你必须动态地“生成”你的SQL查询。当用户可以在我的数据库中创建/删除/更改表时,我会感到奇怪的感觉!

EAV模型的另一个不错的功能是,您可以轻松地合并两个列表,而无需删除和更改表。

修改:

我认为您需要另一个名为ListRows的表来告诉您哪些ListData记录连续存在!

答案 1 :(得分:2)

我以前经历过这样的事情 - 我不想分享实际的表模式,所以让我们使用一些建议的表结构做一些思考练习:

  • 让我们有一个lists表,其中包含我所有列表的列表
  • 让我们还有一个包含元数据(列名称)的columns
  • 现在我们需要一个包含列值<{li>的values
  • 我们还需要一个rows表,其中包含所有行的列表,否则很难计算出实际有多少行

为了简单起见,我们只需将所有内容都设为字符串(VARCAHR),然后再进行一些查询:

计算表格中的所有行

SELECT COUNT(*) FROM [rows]
JOIN [lists]
    ON [rows].list_id = [Lists].id
WHERE [Lists].name = 'Cars'
嗯,不是太糟糕,相比之下:

SELECT * FROM [Cars]

在表格中插入行

BEGIN TRANSACTION

DECLARE @row_id INT
DECLARE @list_id INT

SELECT @list_id = id FROM [lists] WHERE name = 'Cars'

INSERT INTO [rows] (list_id) VALUES (@list_id)
SELECT @row_id = @@IDENTITY

DECLARE @column_id INT

-- === Need one of these for each column ===
SELECT @column_id = id FROM [columns]
WHERE name = 'Make'
AND list_id = @list_id

INSERT INTO [values] (column_id, row_id, value)
VALUES (@column_id, @row_id, 'Rover')

-- === Need one of these for each column ===
SELECT @column_id = id FROM [columns]
WHERE name = 'Model'
AND list_id = @list_id

INSERT INTO [values] (column_id, row_id, value)
VALUES (@column_id, @row_id, 'Metro')
COMMIT TRANSACTION
嗯,与以下相比,开始有点毛茸茸:

INSERT INTO [Cars] ([Make], [Model}) VALUES ('Rover', 'Metro')

简单查询

我现在厌倦了构建繁琐复杂的SQL语句,所以也许你可以为followng语句提出等效的查询:

SELECT [Model] FROM [Cars] WHRE [Make] = 'Rover'

SELECT [Cars].[Make], [Cars].[Model], [Owners].[Name] FROM [Cars]
JOIN [Owners] ON [Owners].id = [Cars].owner_id
WHERE [Owners].Age > 50

SELECT [Cars].[Make], [Cars].[Model], [Owners].[Name] FROM [Cars]
JOIN [Owners] ON [Owners].id = [Cars].owner_id
JOIN [Addresses] ON [Addresses].id = [Owners].address_id
WHERE [Addresses].City = 'London'

我希望你开始明白这个想法......

简而言之 - 我以前经历过这一点,我可以向您保证,以这种方式在数据库中创建数据库绝对是一件坏事。

如果你需要做任何事情,但是对这些列表进行最基本的查询(我的意思是“我可以将此列表中的所有项目都包括在内吗?”),你应该尝试找一个替代品。

只要每个用户都有自己的数据库,我肯定会推荐CREATE TABLE方法。即使他们不这样做,我仍然建议你至少考虑一下。

答案 2 :(得分:1)

也许潜在的解决方案是创建列表可能涉及这些实体/列表的CREATE TABLE语句?

听起来db结构或模式可以在运行时或用户的命令中更改,所以这样的事情可能会有所帮助吗?

  • 用户想要创建一个前所未见的实体的新列表。称之为电脑。
  • 用户定义属性(screensize,CpuSpeed,AmountRAM,NumberOfCores)
  • 系统允许用户在UI中创建
  • 系统通常会将它们全部设为字符串,除非可以判断所有提供的值何时确实是日期或数字。
  • 构建CREATE脚本,对数据库执行它们。
  • 将用户定义的数据插入到新表中。

正确编码,我们正在处理以下要求:让用户创建新实体。这里没有提到规模。当然,这需要对所有输入进行清理,查询参数化,记录操作等。

下面的否定评论实际上并没有给出任何合理的理由,但会产生一些FUD。我有兴趣解决这个潜在解决方案的任何问题。我们还没有听说过规模,安全性,性能或使用情况(内部局域网与互联网)。

答案 3 :(得分:1)

当用户创建列表时,绝对不应动态创建表。这不是数据库的工作方式。

您的架构是正确的,在我看来,复数也是正确的,但我会移除驼峰案例并将其称为listslist_columnslist_rows和{{ 1}}。

我会通过跳过list_datarows表来进一步改进您的架构,它们没有用处。只需在每个单元格上附加行/列编号,并保持稀疏:不要打扰在数据库中保留空单元格。您保留了基于行/列查询/排序的功能,您的查询将(可能非常)更快,因为columns的数量将减少,您将不必疯狂加入链接你的数据回到了它的表格。

这是完整的架构:

list_cells

答案 4 :(得分:0)

听起来您可能已在您的环境中部署了Sharepoint。

考虑将您的应用程序与Sharepoint集成,并将其作为您的数据存储区。当你可以利用它时,无需重新创建你喜欢的所有关于Sharepoint的东西。

需要进行一些配置,但您可以调用SP Web服务来为您提供CRUD列表数据。

Sharepoint 2010还可以通过OData公开列表,这可以很容易地从任何应用程序中使用。