2012-07-09 30 views
0

我对SQL很陌生,在我的表中使用外键时遇到了一些麻烦 - 它需要大量的查询来插入/更新这样的表的一行。如何使用外键添加/更新表中的行时最大限度地减少查询数

所以,基本上我有4个表,我用来存储“键=值”的关系为IRC通道的结构:

msg 
    -id integer //primary key 
    -srv_id  //integer 
    -chan_id //integer 
    -usr_id  //integer 
    -key  //text 
    -value  //text 

srv 
    -id //integer primary key 
    -name //text 

chan 
    -id //integer primary key 
    -name //text 

usr 
    -id //integer primary key 
    -name //text 

srv_id,chan_id和味精表usr_id从未来三代表的外键。

我需要注意的是,用户可以覆盖其他的键,所以当用户添加“键=值”关系时,我需要在msg表中插入新行或更新现有值和usr_name给定srv_name,chan_name和钥匙。

问题:我怎么有效地添加行(或更新它,如果给定的密钥味精表已经存在)知道:msg.key =“some_msg_key”,msg.value =“new_msg_value”,srv.name ='some_srv_name',chan.name ='some_chan_name'和usr.name ='some_usr_name',可能不在表格中。

现在我在做这样的事情:

SELECT id FROM srv WHERE name = 'some_srv_name' 

检查,如果我有ID,如果不是我做

INSERT INTO srv WHERE name = 'some_srv_name' 

,然后我得到它的ID与

SELECT id FROM srv WHERE name = 'some_srv_name' 

然后我对chan表和usr表做同样的事情。
当srv,chan和urs的名字是全新的时,它有9个查询。这不是很可怕吗?这并不是最终目标 - 我的目标是向msg表添加新行或者在存在的情况下更新它(基于键值)。

所以,当我知道“some_srv_name”,“some_chan_name”和“some_usr_name”是表,我得到了他们的身份证,我检查是否存在有这样的id和关键值的行=“some_msg_key”:

SELECT id FROM msg WHERE srv_id = 'id_from_previous_queries' AND chan_id = 'id_from_previous_queries' AND key = 'some_msg_key' 

,如果我得到任何东西,我知道,行存在,我需要更新它,所以我做的:

UPDATE msg SET usr_id = 'id_from_previous_queries', key = 'some_msg_key', value = 'new_msg_value' WHERE id = 'id_from_right_above' 

如果我没出息,我知道有没有这样的行,我需要插入它:

INSERT INTO msg VALUES(null, 'id_from_previous_queries', 'id_from_previous_queries', 'id_from_previous_queries', 'some_msg_key', 'new_msg_value') 

因此,总共我做了5-11个查询。

我不知道是否有更少的查询添加/更新msg表中的行的更好的方法知道只有srv,陈和usr可能不在表中的名称尚未。

注意:我用SQLite

+0

好的,有人告诉我有关INSERT或REPLACE INTO,这肯定会有所帮助。 – None 2012-07-09 14:58:09

回答

1

是的,你可以更容易地做到这一点。首先建立查找表,然后建立最终的味精表。假设你在表src中有非标准化的数据,并且你想插入它。

首先,你必须将新值到每个查找表,使用的查询,如:

insert into srv(name) 
    select distinct name 
    from src 
    where name not in (select name from srv) 

ID应该自动宣布它是一个自动递增/身份证/串行列分配(视在你的数据库上)。

为每个查找表执行此操作。然后执行以下操作以插入msg表:

insert into msg(srv_id, chan_id, usr_id, key, value) 
    select srv.srv_id, chan.chan_id, . . . 
    from src join 
     srv 
     on src.name = srv.src_name join 
     chan 
     on chan.name = srv.chan_name . . . 
0

你不应该改变主键的值。您应该查找如何使用存储过程和触发器。

+0

我没有改变主键的值。 – None 2012-07-09 14:56:35

+0

对不起。我看着你的查询错误 – 2012-07-09 17:03:14

相关问题