最近遇到一个这样的问题,现在有这么几张表。user customer identity, 一个user拥有多个customer,一个customer拥有多个identity.
User 表
id integer, name varchar(255), password varchar(255)
custmer表
id integer, user_id, integer name, varchar(255) phone,varchar(11)
identify表
id, integer customer_id, integer key, varchar(255) value varchar(255)
问题出在这张identity表上。没有存user_id。导致的问题是在找某个user下面所有有某个idetity的customer的时候很费劲。
首先得从customer表中找到user的所有的customer,然后去遍历identity表,找到customer并且是有某个值的customer。如果用rails的activerecord会很麻烦。所以用sql去查询,但是似乎也不是很简单
select * from customer as c , identity as i where(c.user_id = user_id and c.id = i.customer_id and i.key = 'key' and i.value='value')
这样似乎会简单一些。(为什么没有用表关联,是因为customer这张表是数据基本表,很多表都依赖他,不像让它变得太复杂)看用sql语句会简单一些。但是看起来还是麻烦一些。因为在做反向查询的时候会不断的去连表查。解决办法是给identity表加上一个user_id字段。使用有两种方式。sql和rails migration。先说sql
alert table identity add user_id int(10) not null default 0 ; update identify as i set user_id=(select user_id from customer as c wherer i.customer_id = c.id) //update这条sql语句没有试过,当时考虑到它又缺点,没有采用。
刚刚说道这条sql语句有问题,是因为在这里添加了user_id并对旧数据进行了兼容。但是程序中某些地方在存customer的identity的时候并没有提供user_id,所以采用的rails的activityrecord,前半部分和sql一样
add_column :identity, :user_id, :ingeter Identity.all.each do |item| customer = Customer.find_by( {:customer_id => item.customer_id}) if customer.present? && customer.user_id.present? && item.user_id.nil? item.user_id = customer.user_id item.save end end
这部分和上面的sql语句大同小异,只是增加了一些冗余判断,是因为发现在执行sql的时候会报出user_id为空的时候,下面说另外一部分:怎么兼容旧接口。
class Identity before_save: save_default_user_id def save_default_user_id if self.user_id.nil? customer = Customer.find_by( {:id => self.customer_Id} ) if customer.present? && customer.user_id.present? self.user_id = customer.user_id end end end end
这块是rails提供的before_save 他能够在commit之前做一些事,这样就能够保证旧的接口能够继续工作了。
在开发的过程中,开发并不是最复杂的,旧数据的兼容才是重要的,我们要考虑的不简单的只是功能的实现。