我对 SQL 很陌生,并且在我的表中使用外键时遇到了一些麻烦——插入/更新此类表的单行需要大量查询。
所以,基本上我有一个由 4 个表组成的结构,用于存储 IRC 频道的“key = value”关系:
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
msg 表中的 srv_id、chan_id 和 usr_id 是接下来三个表的外键。
我需要注意的是,用户可以覆盖其他人的键,因此当用户添加“键 = 值”关系时,我需要在 msg 表中插入新行或更新给定 srv_name、chan_name 和键的现有值和 usr_name。
问题:知道:msg.key = 'some_msg_key', msg.value = 'new_msg_value', srv.name = 'some_srv_name', chan 如何有效地添加一行(或者如果给定的键已经存在于 msg 表中则更新它) .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 时,我检查是否存在具有此类 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、chan 和 usr 的名称。
注意:我使用 SQLite