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

时间:2012-01-13 14:02:37

标签: php mysql database database-design

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

正如我所设想的那样,单个Patient对象具有基本属性,如idnameaddress,然后每个Patient也有一个Medication个对象(med_name, dose, reason),Condition个对象(cond_name, date, notes)以及其他此类对象(过敏,家族史等)的数组。 我的第一个想法是拥有一个包含表格的数据库模式,如下所示:

  • 患者(身份证,姓名,地址,......)
  • 药物(patient_id,med_name,剂量,原因)
  • 条件(patient_id,cond_name,日期,备注)
  • ...

然而,这对我来说似乎不对。添加新的药物或条件很容易,但删除或编辑现有的药物或条件似乎是非常低效的 - 我必须在medications表中搜索与patient_id匹配的行。 med_namedosereason字段,然后使用新数据删除/编辑它。我可以在medicationsconditions表中添加一些主键,以便更有效地找到要编辑的行,但这看起来像是一段任意数据。

那么如果我只有一个包含以下架构的表呢?

  • 患者(身份证,姓名,地址,药物,conds,......)

medsconds只是MedicationCondition对象数组的表示(比方说,二进制)? PHP可以解释这些数据,并根据需要在数据库中获取和更新它。

欢迎任何有关最佳做法的想法。我也在考虑切换到Ruby on Rails,所以如果这会影响我应该做出的任何决定,我也有兴趣听到它。非常感谢大家。

3 个答案:

答案 0 :(得分:4)

对数据进行编码的“不良”或“好”取决于您的需求。如果您从不需要在那些'meds'和'conds'表中引用单个较小的数据块,那么就没有问题。

然而,你实际上是在将数据库简化为一个比智慧更傻的存储系统,并且失去了SQL数据库中“关系”部分的好处。

e.g。如果你需要运行一个查询“查找所有服用伟哥并有心脏病的患者”,那么DBMS将无法直接运行该查询,因为它不知道你是如何“隐藏”伟哥的这两个字段中的/ heart条件数据,而对于正确规范化的数据库,你有:

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')

并且DBMS自动处理所有事情。如果您将所有内容编码到单个字段中,那么您将陷入子字符串操作(假设数据采用某种可读的ascii格式),或者更糟糕的是,必须将整个数据库吸入客户端应用程序,解码每个字段,检查其内容,然后扔掉所有不含伟哥或心脏病的东西 - 非常低效。

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

  

我必须在药物表中搜索一行   将patient_id与旧的med_name,剂量和原因字段匹配,   然后使用新数据删除/编辑它。

假设密钥是{patient_id,med_name,start_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')