Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在数据库中保存动态列表的首选方法是什么?_Sql_Database_Database Design - Fatal编程技术网

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

Sql 在数据库中保存动态列表的首选方法是什么?,sql,database,database-design,Sql,Database,Database Design,在我们的应用程序中,用户可以创建不同的列表(如sharepoint),例如,用户可以创建汽车列表(名称、型号、品牌)和学生列表(姓名、出生日期、地址、国籍),e.t.c 我们的应用程序应该能够查询列表的不同列,所以我们不能只序列化每一行并将其保存在一行中 我应该在运行时为每个新创建的列表创建一个新表吗?如果这是最好的解决方案,那么我想Microsoft SharePoint可能也会这么做 我应该使用以下模式吗 Lists (Id, Name) ListColumns (Id, ListId, N

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

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

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

我应该使用以下模式吗

Lists (Id, Name)
ListColumns (Id, ListId, Name)
ListRows (Id, ListId)
ListData(RowId, ColumnId, Value)
虽然一行在列表数据表中创建的行数与列表中的列数相同,但这感觉不太对


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

也许一个潜在的解决方案是创建列表,可以包括为这些实体/列表创建
CREATE TABLE
语句

听起来数据库结构或模式可以在运行时更改,或者在用户的命令下更改,所以这样做可能会有所帮助吗

  • 用户希望创建以前从未见过的实体的新列表。叫它电脑
  • 用户定义属性(屏幕大小、CpuSpeed、AmountRAM、NumberOfCores)
  • 系统允许用户在UI中创建
  • 系统通常允许它们都是字符串,除非可以告诉我们何时所有提供的值都是日期或数字
  • 构建创建脚本,针对数据库执行它们
  • 将用户定义的数据插入到新表中
正确编码后,我们将处理给定的需求:让用户创建新实体。这里没有提到规模。当然,这需要对所有输入进行清理、参数化查询、记录操作等

下面的负面评论实际上并没有给出任何好的理由,但却制造了一点FUD。我有兴趣解决这个潜在解决方案的任何问题。我们还没有听说过规模、安全性、性能或使用情况(内部LAN与internet)。

您所做的就是所谓的

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

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

这很好。我不喜欢动态创建表,因为它可能会弄乱数据库,您必须动态“生成”SQL查询。当用户可以在我的数据库中创建/删除/更改表时,我会有一种奇怪的感觉

EAV模型的另一个很好的特性是,您可以轻松地合并两个列表,而无需删除和更改表

编辑:


我认为您需要另一个名为ListRows的表,它告诉您哪些ListData记录属于同一行

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

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

这需要进行一些配置,但您可以调用SP web服务来为您的列表数据进行CRUD


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

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

您的模式是正确的,在我看来,复数形式也是正确的,尽管我会删除驼峰大小写,并将它们称为
列表
列表列
列表行
列表数据

我将通过跳过
表来进一步改进您的模式,它们没有任何作用。只需在每个单元格上附加一个行/列编号,并保持稀疏:不要在数据库中保留空单元格。您保留了基于行/列的查询/排序功能,您的查询将(可能会)更快,因为
list\u单元格的数量将减少,并且您不必进行任何疯狂的连接来将数据链接回其表

以下是完整的模式:

create table lists (
  id int primary key,
  name varchar(25) not null
);

create table list_cells (
  id int primary key,
  list_id int not null references lists(id)
    on delete cascade on update cascade,
  row int not null,
  col int not null,
  data varchar(25) not null
);

我以前也经历过类似的情况-我不想分享实际的表模式,所以让我们使用一些建议的表结构进行一些思考练习:

  • 让我们有一个
    列表
    表,其中包含所有我的列表
  • 让我们也有一个
    表,其中包含元数据(列名)
  • 现在我们需要一个包含列值的
    values
  • 我们还需要一个包含所有行的列表的
    rows
    表,否则很难计算出实际有多少行
为了简单起见,让我们将所有内容都设置为字符串(
VARCAHR
),并尝试提出一些查询:

统计表中的所有行

SELECT COUNT(*) FROM [rows]
JOIN [lists]
    ON [rows].list_id = [Lists].id
WHERE [Lists].name = '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
嗯,还不错,相比之下:

SELECT * FROM [Cars]
INSERT INTO [Cars] ([Make], [Model}) VALUES ('Rover', 'Metro')
将行插入表中

SELECT COUNT(*) FROM [rows]
JOIN [lists]
    ON [rows].list_id = [Lists].id
WHERE [Lists].name = '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
嗯,相比之下,开始有点毛茸茸的了:

SELECT * FROM [Cars]
INSERT INTO [Cars] ([Make], [Model}) VALUES ('Rover', 'Metro')
简单查询

我现在已经厌倦了构造繁琐复杂的SQL语句,因此您可以尝试对以下语句进行等效查询:

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'
我希望你开始明白了

简言之,我以前经历过这种情况,我可以向您保证,以这种方式在数据库中创建数据库肯定是件坏事

如果您需要对这些列表进行最基本的查询(我的字面意思是“我可以拥有此列表中的所有项目吗?”),您应该尝试寻找替代方法

只要每个用户都有自己的数据库,我肯定会推荐
createtable
方法。即使他们不知道,我还是建议你至少考虑一下。