Mysql 数据库中的数据库(表设计)
可能重复:Mysql 数据库中的数据库(表设计),mysql,sql,sql-server,oracle,postgresql,Mysql,Sql,Sql Server,Oracle,Postgresql,可能重复: 我需要在数据库中创建一个数据库。这个问题涉及到。我将尝试详细解释我要做的事情,并提供代码示例。基本上,我希望能够在数据库中创建动态表。例如,我将有一个网页,允许用户使用列和数据创建自己的表。以下是我提出的数据库设计: aColumn aDataType aRow aTable zBit zDateTime zMoney zNumber zText 以z开头的表是特定数据进入的数据,如int、datetime值等。列是属于特定表的列。aRow标识aTable中的特定行。以下是数据库
我需要在数据库中创建一个数据库。这个问题涉及到。我将尝试详细解释我要做的事情,并提供代码示例。基本上,我希望能够在数据库中创建动态表。例如,我将有一个网页,允许用户使用列和数据创建自己的表。以下是我提出的数据库设计:
aColumn
aDataType
aRow
aTable
zBit
zDateTime
zMoney
zNumber
zText
以z
开头的表是特定数据进入的数据,如int、datetime值等。列是属于特定表的列。aRow标识aTable中的特定行。以下是数据库设计:
aTable: Id, name
aColumn: Id, Name, aTable, aDataType
aDataType: Id, Name
aRow: Id, aTable
zBit: Id, aRow, aColumn, Data(Bit)
zDateTime: Id, aRow, aColumn, Data (DateTime)
zMoney: Id, aRow, aColumn, Data (Money)
zNumber: Id, aRow, aColumn, Data (INT)
zText: Id, aRow, aColumn, Data (nvarchar(MAX))
下面是我用来启动和运行它的一些示例数据:
aTable
Id Name
1 Users
Id Name
1 Number
2 Text
aColumns
Id Name aTable aDataType
1 Name 1 2
2 UserId 1 1
3 Occupation 1 2
Table Column DataType Row Data
1 UserId Number 1 1245
1 UserId Number 2 56
1 Name Text 1 Sara
1 Name Text 2 Jake
Id Name aTable aDataType
1 Name 1 2
2 UserId 1 1
3 Occupation 1 2
aDataType
Id Name
1 Users
Id Name
1 Number
2 Text
aRow
Id aTable
1 1
2 1
a数量
Id aRow aColumn Data
1 1 1 1245
2 2 2 56
aText
Id aRow aColumn Data
1 1 1 Sara
2 2 1 Jake
所有其他z*表均为空
以下是创建动态表的查询:
select t.[Id] as [Table], c.Name as [Column], dt.Name as [DataType], r.[Id] as [Row], cast(v.Data as nvarchar(MAX)) as Data from [pod].[dbo].[aTable] t
INNER JOIN [pod].[dbo].[aColumn] c on t.Id = c.[aTable]
INNER JOIN [pod].[dbo].[aDataType] dt on c.[aDataType] = dt.Id
INNER JOIN [pod].[dbo].[aRow] r on t.[Id] = r.[aTable]
INNER JOIN [pod].[dbo].[zBit] v on c.[Id] = v.aColumn and r.[Id] = v.[aRow]
UNION ALL
select t.[Id] as [Table], c.Name as [Column], dt.Name as [DataType], r.[Id] as [Row], cast(v.Data as nvarchar(MAX)) as Data from [pod].[dbo].[aTable] t
INNER JOIN [pod].[dbo].[aColumn] c on t.Id = c.[aTable]
INNER JOIN [pod].[dbo].[aDataType] dt on c.[aDataType] = dt.Id
INNER JOIN [pod].[dbo].[aRow] r on t.[Id] = r.[aTable]
INNER JOIN [pod].[dbo].[zDateTime] v on c.[Id] = v.aColumn and r.[Id] = v.[aRow]
UNION ALL
select t.[Id] as [Table], c.Name as [Column], dt.Name as [DataType], r.[Id] as [Row], cast(v.Data as nvarchar(MAX)) as Data from [pod].[dbo].[aTable] t
INNER JOIN [pod].[dbo].[aColumn] c on t.Id = c.[aTable]
INNER JOIN [pod].[dbo].[aDataType] dt on c.[aDataType] = dt.Id
INNER JOIN [pod].[dbo].[aRow] r on t.[Id] = r.[aTable]
INNER JOIN [pod].[dbo].[zMoney] v on c.[Id] = v.aColumn and r.[Id] = v.[aRow]
UNION ALL
select t.[Id] as [Table], c.Name as [Column], dt.Name as [DataType], r.[Id] as [Row], cast(v.Data as nvarchar(MAX)) as Data from [pod].[dbo].[aTable] t
INNER JOIN [pod].[dbo].[aColumn] c on t.Id = c.[aTable]
INNER JOIN [pod].[dbo].[aDataType] dt on c.[aDataType] = dt.Id
INNER JOIN [pod].[dbo].[aRow] r on t.[Id] = r.[aTable]
INNER JOIN [pod].[dbo].[zMoney] v on c.[Id] = v.aColumn and r.[Id] = v.[aRow]
UNION ALL
select t.[Id] as [Table], c.Name as [Column], dt.Name as [DataType], r.[Id] as [Row], cast(v.Data as nvarchar(MAX)) as Data from [pod].[dbo].[aTable] t
INNER JOIN [pod].[dbo].[aColumn] c on t.Id = c.[aTable]
INNER JOIN [pod].[dbo].[aDataType] dt on c.[aDataType] = dt.Id
INNER JOIN [pod].[dbo].[aRow] r on t.[Id] = r.[aTable]
INNER JOIN [pod].[dbo].[zNumber] v on c.[Id] = v.aColumn and r.[Id] = v.[aRow]
UNION ALL
select t.[Id] as [Table], c.Name as [Column], dt.Name as [DataType], r.[Id] as [Row], cast(v.Data as nvarchar(MAX)) as Data from [pod].[dbo].[aTable] t
INNER JOIN [pod].[dbo].[aColumn] c on t.Id = c.[aTable]
INNER JOIN [pod].[dbo].[aDataType] dt on c.[aDataType] = dt.Id
INNER JOIN [pod].[dbo].[aRow] r on t.[Id] = r.[aTable]
INNER JOIN [pod].[dbo].[zText] v on c.[Id] = v.aColumn and r.[Id] = v.[aRow]
以下是此查询的一个块:
select t.[Id] as [Table], c.Name as [Column], dt.Name as [DataType], r.[Id] as [Row], cast(v.Data as nvarchar(MAX)) as Data from [pod].[dbo].[aTable] t
INNER JOIN [pod].[dbo].[aColumn] c on t.Id = c.[aTable]
INNER JOIN [pod].[dbo].[aDataType] dt on c.[aDataType] = dt.Id
INNER JOIN [pod].[dbo].[aRow] r on t.[Id] = r.[aTable]
INNER JOIN [pod].[dbo].[zText] v on c.[Id] = v.aColumn and r.[Id] = v.[aRow]
正如您在这里看到的,一段数据(z*表)由一行和一列标识。当我运行此查询时,我得到以下信息:
结果
Id Name aTable aDataType
1 Name 1 2
2 UserId 1 1
3 Occupation 1 2
Table Column DataType Row Data
1 UserId Number 1 1245
1 UserId Number 2 56
1 Name Text 1 Sara
1 Name Text 2 Jake
Id Name aTable aDataType
1 Name 1 2
2 UserId 1 1
3 Occupation 1 2
以下是我想要的结果:
(如果列是未知的,我不知道如何将这些行转换为列)
大问题 这个表应该有3列,记得吗 aColumns
Id Name aTable aDataType
1 Name 1 2
2 UserId 1 1
3 Occupation 1 2
Table Column DataType Row Data
1 UserId Number 1 1245
1 UserId Number 2 56
1 Name Text 1 Sara
1 Name Text 2 Jake
Id Name aTable aDataType
1 Name 1 2
2 UserId 1 1
3 Occupation 1 2
因此,我的最终预期结果是:
Row UserId Name Occupation
1 1245 Sara NULL
2 56 Jake NULL
在结果中,我还需要对列进行排序。这可能吗。哪些数据库支持这种功能。我对任何能够做到这一点的数据库都持开放态度。那么,您可能想看看您的数据设计 基本上,您可以有一个带有表名的表,以及表上的一些其他元数据 然后,您可以为这些行中的每一行创建一个表,以包含列数据,例如数据类型和名称 然后,您有一个表格,在其中您将每列的值放在一个长表格中 这允许您动态创建表,或动态添加/删除行 要比较relational和EAV,您可以查看以下问题: 但是,如果您想拥有此数据的关系视图,那么您需要创建触发器来帮助保持视图的最新状态,要使其正常工作,这可能需要大量的工作。如果您不需要关系视图,那么就可以了 另一种方法是使用NoSQL数据库(),因为不必设置模式,所以您可以只存储该行所需的列
在这一点上,我将采用NoSQL方式,因为有许多数据库可以工作,并且您需要进行的重新设计是最少的。您可能需要查看数据的设计 基本上,您可以有一个带有表名的表,以及表上的一些其他元数据 然后,您可以为这些行中的每一行创建一个表,以包含列数据,例如数据类型和名称 然后,您有一个表格,在其中您将每列的值放在一个长表格中 这允许您动态创建表,或动态添加/删除行 要比较relational和EAV,您可以查看以下问题: 但是,如果您想拥有此数据的关系视图,那么您需要创建触发器来帮助保持视图的最新状态,要使其正常工作,这可能需要大量的工作。如果您不需要关系视图,那么就可以了 另一种方法是使用NoSQL数据库(),因为不必设置模式,所以您可以只存储该行所需的列
在这一点上,我将采用NoSQL方式,因为有许多数据库可以工作,并且您需要进行的重新设计非常少。对于问题的最后一部分,您将询问如何对EAV模式进行查询。一些数据库通过对SQL标准的扩展来支持这一点,而另一些数据库则根本不支持。为了便于携带,您必须在应用程序中实现。PostgreSQL为此提供了最新的解决方案 如果你走这条路,你迟早会后悔的。它在某些有限的情况下是有用的,但是它不适合关系模型,并且会导致很多痛苦和问题,其中最重要的是糟糕的性能 相反,请考虑:
- 如果可能的话,重新设计,这样就不需要动态模式。在您的情况下可能不可能,因为您的明确需求是基于web的数据库应用程序的用户可编辑模式,但在大多数情况下,这是正确的选择
- 使用
,ALTER TABLE
等动态创建/删除模式。一些数据库在这方面比其他数据库好得多。PostgreSQL的事务性DDL非常有用。要避免这成为性能和维护的噩梦,需要谨慎,但如果您试图用动态结构对关系数据库建模,这可能是最明智的选择create TABLE
- 为类似EAV的查询而优化的键/值存储;看见请注意,这些系统中的许多都不提供完整的ACID语义,并且可能具有有限的查询语言,因此您可以在应用程序中完成更多的工作
- 在数据库中存储XML或JSON。您可以使用关系数据库来实现这一点,但使用文档数据库可能会更好。与K/V商店相同的注意事项也适用。如果您在应用程序中执行所有查询逻辑,并且您的数据量不太大,那么这种方法可以正常工作
- 使用特定于数据库的功能,如PostgreSQL的
,在需要时支持任意键/值存储,并在不需要k/v的情况下使用标准关系设计。如果您希望将关系作为输出,那么它仍然是一个主要的PITA,涉及低效的交叉表查询和连接hstore