如何设计一个布局可能随时间变化的通用数据库?

Maw*_*awg 8 php sql database database-design dynamic-sql

这是一个棘手的问题 - 我如何以编程方式创建和查询其内容我无法预见的数据库?

我正在实现一个通用的输入表单系统.用户可以使用WYSIWYG布局创建PHP表单,并将其用于他希望的任何目的.他也可以查询输入.

所以,我们有三个阶段:

  1. 设计并生成表单.虽然可以稍后编辑表单,但这是一次性过程.这设计了数据库.
  2. 有人或几个人使用表格 - 例如每日销售报告,库存,工资单等.他们对表格的输入被写入数据库.
  3. 其他人,也许是管理层,可以查询数据库并生成报告.

由于这些表单是通用的,我无法预测数据库结构 - 除了说它将反映HTML表单字段并且包括来自编辑框,备忘录,单选按钮等的集合的数据输入.

问题和评论:

A)如何在表和列方面最好地构建数据库?主键怎么样?我的第一个想法是使用控件名称来标识每一列,然后我意识到用户可以编辑表单并重命名,这样可能"名称"变为"员工"或"工资"变为":薪水".我倾向于每个人的唯一编号.

B)如何最好地键入行?我在想一个允许我查询的时间戳和来自A的行Id的列

C)我必须处理列重命名/插入/删除.敌人删除,我不确定是否从数据库中删除数据.即使用户不再从表单输入它,他也可能希望查询先前输入的内容.或者可能存在一些保留数据的法律要求.列重命名/插入/删除中的任何问题?

D)对于查询,我可以让我的PHP查询数据库以获取列名并生成一个带有列表的表单,其中每个条目都有一个数据库列名,一个复选框说明它是否应该在查询中使用,并且基于列类型,一些选择标准.这应该足以构建像"position ='高级推销员'和薪水> 50k"这样的搜索.

E)我可能必须生成一些花哨的图表 - 图表,直方图,饼图等,以便随着时间的推移查询数值数据的结果.我需要为此找到一些好的FOSS PHP.

F)我还忘记了什么?

对我来说这一切看起来都很棘手,但我是数据库n00b - 也许你对大师来说很简单?


编辑:请不要告诉我不要这样做.我没有任何选择:-(

编辑:在现实生活中,我不希望列重命名/插入/删除频繁.但是,运行几个月后可能需要更改数据库.我确信这种情况经常发生.我担心我已经严重地提出了这个问题并且人们认为每10分钟左右就会发生变化.

实际上,我的用户将在布置表单时定义数据库.他们可能第一次就做对了,永远不会改变它 - 特别是如果他们从纸质表格转换.即使他们决定改变,这可能只发生一次或两次,数月或数年后 - 这可能发生在任何数据库中.

我不认为我在这里有一个特例,也不认为我们应该专注于改变.或许更好地专注于联系 - 什么是一个好的主键计划?或许,对于一个文本输入,一个数字和一个备忘录?

APC*_*APC 9

"对我来说这一切看起来都很棘手,但我是数据库n00b - 也许这对你们大师来说很简单?"

不,这真的棘手.从根本上说,您所描述的不是数据库应用程序,而是数据库应用程序构建器.实际上,听起来好像您想要编写类似Google App Engine或MS Access的Web版本的代码.编写这样的工具将花费大量时间和专业知识.

Google通过使用其BigTable平台实施了灵活的架构.它允许您随意弯曲架构.问题是,这种灵活性使得很难编写诸如"position ='高级销售员'和薪水> 50k"之类的查询.

所以我认为NoSQL方法不是你需要的.您希望构建一个生成和维护RDBMS模式的应用程序.这意味着您需要设计一个元数据存储库,您可以从中生成动态SQL以构建和更改用户的模式,并生成前端.

您的元数据架构需要存储的东西

对于模式生成:

  • 外键关系(EMPLOYEE在DEPARTMENT中工作)
  • 唯一的业务键(只能有一个名为"Sales"的DEPARTMENT)
  • 参考数据(EMPLOYEE.POSITION的许可值)
  • 列数据类型,大小等
  • 列是否可选(即NULL或NOT NULL)
  • 复杂的业务规则(员工奖金不能超过工资的15%)
  • 列的默认值

对于前端一代

  • 显示名称或标签("工资","薪水")
  • 小部件(下拉列表,弹出日历)
  • 隐藏的领域
  • 派生字段
  • 帮助文字,提示
  • 客户端验证(关联的JavaScript等)

最后一点指出了提案中潜在的复杂性:像Joe Soap这样的常规表单设计者无法将JS表示为(比如说)验证输入值介于X和Y之间,因此您将拥有使用模板化规则导出它.

这些绝不是详尽的清单,它只是我的头脑.

对于主键,我建议您使用GUID数据类型的列.时间戳不能保证是唯一的,但如果你在一个操作系统上运行你的数据库到六个地方(即不是Windows),你就不太可能发生冲突.

遗言

"我的第一个想法是使用控件名称来标识每一列,然后我意识到用户可以编辑表单并重命名,这样可能"名称"变为"员工"或"工资"变为":工资".我倾向于每个人都有一个独特的号码.

我以前构建过数据库模式生成器.他们很难过.可能很难的一件事是调试动态SQL.因此,让自己更容易:使用表和列的真实姓名.仅仅因为应用程序用户现在想要查看标题为HEADCOUNT的表单,这并不意味着您必须重命名EMPLOYEES表.因此需要将显示的标签与模式对象名称分开.否则你会发现自己试图弄清楚这个生成的SQL语句失败的原因:

update table_11123
set col_55542 = 'HERRING'
where col_55569 = 'Bootle'
/
Run Code Online (Sandbox Code Playgroud)

那种疯狂就是谎言.


Tho*_*mas 7

实质上,您正在询问如何构建没有规范的应用程序.关系数据库的设计并非如此,以便您可以有效地执行此操作.这个问题的常见方法是实体 - 属性 - 值设计,对于您想要使用它的系统类型,失败的几率几乎是100%.

例如,名为"Name"的列可能成为"Salary"是没有意义的.如果工资值可能有"Fred","Bob",100K,1000,"很多",那么报告在哪里可以获得总工资?数据库的设计并不是为了让任何人放置任何东西.成功的数据库模式需要结构,这意味着在需要存储的内容和原因方面需要努力.

因此,为了回答你的问题,我会重新考虑这个问题.尝试制作可以在宇宙中存储任何内容的应用程序的整个方法并不是成功的秘诀.

  • @mawg - 您缺乏关于任何数据库驱动的应用程序中最关键部分的规范:数据本身.报告将真正解开的地方.实际上,在构建将驱动报告的数据之前,您需要先询问架构.存储只是难题的一小部分.杀死该项目的是性能和维护.这是一篇关于一个人使用EAV的经历的精彩文章,并注意他使用的伟大比喻.http://www.simple-talk.com/opinion/opinion-pieces/bad-carma/ (2认同)
  • @mawg - 如果预计模式的更改很少,为什么不能提前收集规范?使用标准列构建规范化数据库会好得多,也便宜得多.实际上,定制构建三个不同的数据库比构建一个EAV以统治它们以存储所有三个系统的信息要便宜. (2认同)