Php 将面向对象的数据直接编码到关系数据库中的单行中被认为是不好的形式吗?

Php 将面向对象的数据直接编码到关系数据库中的单行中被认为是不好的形式吗?,php,mysql,database,database-design,Php,Mysql,Database,Database Design,我对数据库比较陌生,所以如果有一个明显的方法来解决这个问题,或者我缺少一些基本的过程,我很抱歉。我正在一个涉及患者病历的web应用程序中使用PHP和MySQL。一个要求是用户能够从网页上查看和编辑病历 正如我所设想的,一个患者对象具有基本属性,如id、姓名、地址,然后每个患者还具有一系列药物对象(药物名称、剂量、原因)、条件对象(患者姓名、日期、注释),以及其他此类物品(过敏、家族史等)我的第一个想法是创建一个数据库模式,其中包含如下表: 患者(身份证、姓名、地址等) 药物(患者id、医生姓名

我对数据库比较陌生,所以如果有一个明显的方法来解决这个问题,或者我缺少一些基本的过程,我很抱歉。我正在一个涉及患者病历的web应用程序中使用PHP和MySQL。一个要求是用户能够从网页上查看和编辑病历

正如我所设想的,一个
患者
对象具有基本属性,如
id
姓名
、地址,然后每个
患者
还具有一系列
药物
对象(
药物名称、剂量、原因
)、
条件
对象(
患者姓名、日期、注释
),以及其他此类物品(过敏、家族史等)我的第一个想法是创建一个数据库模式,其中包含如下表:

  • 患者(身份证、姓名、地址等)
  • 药物(患者id、医生姓名、剂量、原因)
  • 病情(患者id、病情名称、日期、备注)
然而,在我看来,这似乎是错误的。添加新的药物或条件很容易,但删除或编辑现有药物或条件似乎效率低下——比如说,我必须在
药物
表中搜索匹配
患者id
与旧
医疗名称
剂量
原因
字段的行,然后用新数据删除/编辑它。我可以在
药物
条件
表中添加一些主键,以便更高效地查找要编辑的行,但这看起来像是一个任意的数据块

那么,如果我只有一个具有以下模式的表呢?

  • 患者(身份证、姓名、地址、药物、病情等)
其中
med
conds
只是
medicing
Condition
对象数组的简单表示(比如二进制)?PHP可以解释这些数据,并根据需要在数据库中获取和更新这些数据


欢迎对这里的最佳实践提出任何想法。我也在考虑切换到RubyonRails,所以如果这影响到我应该做出的任何决定,我也很有兴趣听到这一点。非常感谢各位。

这打破了第一个正常形式。您永远不能以这种方式查询对象属性


如果您有对象,我建议您使用ORM解决方案,或者使用对象数据库。

这打破了第一个正常形式。您永远不能以这种方式查询对象属性


如果您有对象,我建议您使用ORM解决方案,或者使用对象数据库。

这样编码数据的“好坏”取决于您的需要。如果您从不需要引用那些“meds”和“conds”表中的单个较小的数据块,那么就没有问题了

但是,实际上,您正在将数据库简化为比哑存储系统稍微智能一些的存储系统,并且失去了SQL数据库中“关系”部分的好处

e、 g.如果您需要运行“查找所有服用伟哥且患有心脏病的患者”的查询,那么DBMS将无法直接运行该查询,因为它不知道您是如何在这两个字段中“隐藏”伟哥/心脏病数据的,而使用适当规范化的数据库,您将:

SELECT ...
FROM patients
LEFT JOIN conditions ON patients.id = conditions.patient_id
LEFT JOIN meds ON patients.id = meds.patient_id
WHERE (meds.name = 'Viagra') AND (condition.name = 'Heart Disease')

数据库管理系统会自动处理所有信息。如果您将所有内容都编码到单个字段中,那么您将不得不执行子字符串操作(假设数据采用某种可读的ascii格式),或者更糟糕的是,必须将整个数据库拖到客户端应用程序中,解码每个字段,检查其内容,然后扔掉所有不含伟哥或心脏病的东西——效率很低。

这样编码数据的“好坏”取决于你的需要。如果您从不需要引用那些“meds”和“conds”表中的单个较小的数据块,那么就没有问题了

但是,实际上,您正在将数据库简化为比哑存储系统稍微智能一些的存储系统,并且失去了SQL数据库中“关系”部分的好处

e、 g.如果您需要运行“查找所有服用伟哥且患有心脏病的患者”的查询,那么DBMS将无法直接运行该查询,因为它不知道您是如何在这两个字段中“隐藏”伟哥/心脏病数据的,而使用适当规范化的数据库,您将:

SELECT ...
FROM patients
LEFT JOIN conditions ON patients.id = conditions.patient_id
LEFT JOIN meds ON patients.id = meds.patient_id
WHERE (meds.name = 'Viagra') AND (condition.name = 'Heart Disease')
数据库管理系统会自动处理所有信息。如果您将所有内容都编码到单个字段中,那么您将不得不执行子字符串操作(假设数据采用某种可读的ascii格式),或者更糟糕的是,必须将整个数据库拖到客户端应用程序中,解码每个字段,检查其内容,然后扔掉所有不含伟哥或心脏病的东西——效率很低

比如说,我必须在药物表中搜索一行 将患者id与旧医疗名称、剂量和原因字段匹配, 然后用新数据删除/编辑它

假设密钥是{patient\u id,med\u name,start\u date},您只需执行一次更新。没有搜索

update medications
set reason = 'Your newly edited reason, for example.'
where patient_id = ?
  and med_name = ?
  and start_date = ?
您的应用程序将已经知道患者id、医疗名称和开始日期,因为用户必须以某种方式“选择”其中的行,然后才能进行任何更改

update medications
set stop_date = '2012-01-12'
where patient_id = ?
  and med_name = ?
  and start_date = ?

-- I'm using fake data in this one.
insert into medications (patient_id, med_name, start_date, stop_date, dosage)
values (1, 'that same med', '2012-01-12', '2012-01-22', '40mg bid')
如果你要改变剂量,你需要两个改变,一个是更新,一个是插入,这样才有意义

update medications
set stop_date = '2012-01-12'
where patient_id = ?
  and med_name = ?
  and start_date = ?

-- I'm using fake data in this one.
insert into medications (patient_id, med_name, start_date, stop_date, dosage)
values (1, 'that same med', '2012-01-12', '2012-01-22', '40mg bid')
比如说,我必须在药物表中搜索一行 将患者id与旧医疗名称、剂量和原因字段匹配, 然后用新数据删除/编辑它

假设密钥是{patient\u id,med\u name,start\u date},您只需执行一次更新。没有搜索

update medications
set reason = 'Your newly edited reason, for example.'
where patient_id = ?
  and med_name = ?
  and start_date = ?
您的应用程序将已经知道患者id、医疗名称和开始日期,因为用户必须以某种方式“选择”t