如何处理需要与SQLite中的多个id匹配的id?

时间:2018-04-21 08:10:04

标签: sql database sqlite

我是数据库的新手,所以我将首先展示如果我在csv文件中使用简单表格,我会怎么做。目前,我正在构建一个Shiny(R)应用程序来跟踪参与学习的人。我们的想法是确保没有人同时进行多项研究,并且研究之间已经过了足够的时间。

单个表格看起来像这样:

int(xmin)
int(xmax)
int(ymin)
int(ymax)

因此,每项研究都有一个联系人,但有多个任务。其他研究可能会使用相同的任务。

每个任务都应该有一个描述 每个人都可以连接到多个研究(最终数据库有时间戳,以确保不会同时发生),并因此重复相同的任务。

SQLite代码可能看起来像这样

study_title      contact_person    tasks    first_name    last_name
MX9345-3         John Doe          OGTT     Michael       Smith
MX9345-3         John Doe          PVT      Michael       Smith
MX9345-3         John Doe          OGTT     Julia         Barnes
MX9345-3         John Doe          PVT      Julia         Barnes
...

现在我被卡住了。如果我添加主键和外键(例如,CREATE TABLE studies (study_title TEXT, contact_person TEXT); CREATE TABLE tasks (task_name TEXT, description TEXT); CREATE TABLE participants (first_name TEXT, last_name TEXT); 每个研究的ID,以及每个任务和人的外键),主键将重复,这是不可能的。研究由它包含的任务定义(类似于专辑和音乐曲目)。

我应该如何在SQLite中处理这种情况?而且重要的是,INSERT如何在这些情况下完成?我见过很多SELECT示例,但很少有INSERT匹配每个表中的所有ID,例如在正在运行的研究中添加新人时。

2 个答案:

答案 0 :(得分:1)

"处理需要与SQLite中的多个ID匹配的ID?"

对于多对多耦合,请创建额外的耦合表,如下面的static void Main(string[] args) { int[] arr = { 4, 6, 2, 7, 7, 2, 7 }; Compare_competitor(arr); Console.ReadKey(); } study_task表。这是多对多的,因为任务可以在许多研究上进行,研究可以有很多任务。

"确保没有人同时进行多项研究"

这可以通过让每个参与者只有一个当前研究的列来处理(当时没有多于一个的地方)。

participent_task

第一行上的PRAGMA需要制作SQLite(我认为从2009年开始的版本3.6以上)强制执行外键,没有它它只接受外键语法,但不进行控制。

答案 1 :(得分:1)

您所做的是使用表格来映射/引用/关联/关联。

第一步是利用 rowid 的别名,而不是: -

CREATE TABLE studies (study_title TEXT, contact_person TEXT);
CREATE TABLE tasks (task_name TEXT, description TEXT);
CREATE TABLE participants (first_name TEXT, last_name TEXT);

你会使用: -

CREATE TABLE studies (id INTEGER PRIMARY KEY,study_title TEXT, contact_person TEXT);
CREATE TABLE tasks (id INTEGER PRIMARY KEY, task_name TEXT, description TEXT);
CREATE TABLE participants (id INTEGER PRIMARY KEY, first_name TEXT, last_name TEXT);
  • 使用SQLite INTEGER PRIMARY KEY(或INTEGER PRIMARY KEY AUTOINCREMENT)创建列(上面的ID,尽管它们可以包含任何有效的列名)和 rowid 的别名(最大值为每个表1),唯一标识行。
  • 为什么不使用AUTOINCREMENT以及更多信息,请参阅SQLite Autoincrement

插入一些数据进行演示: -

INSERT INTO studies (study_title, contact_person)
    VALUES ('Maths','Mr Smith'),('English','Mrs Taylor'),('Geography','Mary White'),('Phsyics','Mr Smith');

INSERT INTO tasks (task_name,description)
    VALUES ('Task1','Do task 1'),('Task2','Do task 2'),('Task3','Do task 3'),('Task4','Do task 4'),('Mark','Mark the sudies');

INSERT INTO participants (first_name,last_name)
    VALUES ('Tom','Jones'),('Susan','Smythe'),('Sarah','Toms'),('Alan','Francis'),('Julian','MacDonald'),('Fred','Bloggs'),('Rory','Belcher');

第一个映射/参考...表: -

CREATE TABLE IF NOT EXISTS study_task_relationship (study_reference INTEGER, task_reference INTEGER, PRIMARY KEY (study_reference,task_reference));
  • 将研究与任务(许多可能的)进行关联/联系

做一些映射(插入一些数据): -

INSERT INTO study_task_relationship 
    VALUES 
        (1,2), -- Maths Has Task2
        (1,5), -- Maths has Mark Questions
        (2,1), -- English has Task1
        (2,4), -- English has Task4
        (2,5), -- English has Mark questions
        (3,3), -- Geography has Task3
        (3,1), -- Geoegrapyh has Task1
        (3,2), -- Geography has Task2
        (3,5), -- Geography has Mark Questions
        (4,4) -- Physics has Task4
        ;

- 查看每行的评论

列出研究以及任务

SELECT study_title, task_name -- (just want the Study title and task name)
FROM study_task_relationship -- use the mapping table as the main table
JOIN studies ON study_reference = studies.id -- get the related studies
JOIN tasks ON task_reference = tasks.id  -- get the related tasks
ORDER BY study_title -- Order by Study title

导致: -

enter image description here

列出每项研究及其所有任务

SELECT study_title, group_concat(task_name,'...') AS tasklist
FROM study_task_relationship 
JOIN studies ON study_reference = studies.id 
JOIN tasks ON task_reference = tasks.id 
GROUP BY studies.id
ORDER by study_title;

导致: -

enter image description here

添加学习参与者关联表并填充它: -

CREATE TABLE IF NOT EXISTS study_participants_relationship (study_reference INTEGER, participant_reference INTEGER, PRIMARY KEY (study_reference,participant_reference));

INSERT INTO study_participants_relationship
    VALUES
    (1,1), -- Maths has Tom Jones
    (1,5), -- Maths has Julian MacDonald
    (1,6), -- Maths has Fred Bloggs
    (2,4), -- English has Alan Francis
    (2,7), -- English has Rory Belcher
    (3,3), -- Geography has Sarah Toms
    (3,2)  -- Susan Smythe
    ;

作为示例,您现在可以获得参与者列表以及研究标题: -

SELECT study_title, task_name, participants.first_name ||' '||participants.last_name AS fullname 
FROM study_task_relationship
JOIN tasks ON study_task_relationship.task_reference = tasks.id
JOIN studies On study_task_relationship.study_reference = studies.id
JOIN study_participants_relationship ON study_task_relationship.study_reference = study_participants_relationship.study_reference
JOIN participants ON study_participants_relationship.participant_reference = participants.id
ORDER BY fullname, study_title

会导致: -

enter image description here

FOREIGN KEYS

如您所见,没有实际需要定义FOREIGN KEYS。它们实际上只是帮助阻止你无意中做出类似的事情: -

INSERT INTO study_participants_relationship VALUES(30,25);
  • 没有这样的研究,也没有这样的参与者

要利用FOREIGN KEYS,您必须确保它们已启用,最简单的方法是发出命令将它们打开(就好像它是一个普通的SQL语句)。

PRAGMA foreign_keys=1

FOREIGN KEY是一个约束,它会阻止你插入,更新或删除违反约束/规则的行。

基本上规则是定义FOREIGN键的列(子)必须具有一个值,该值在引用的表/列中是父。

所以假设FOREIGN KEYS打开然后编码: -

CREATE TABLE IF NOT EXISTS study_participants_relationship 
(
    study_reference INTEGER REFERENCES studies(id), -- column  foreign key constraint
    participant_reference INTEGER, 
    FOREIGN KEY (participant_reference) REFERENCES participants(id) -- table foreign key constraint
    PRIMARY KEY (study_reference,participant_reference
    )
);

会导致INSERT INTO study_participants_relationship VALUES(30,25);失败,例如

FOREIGN KEY constraint failed: INSERT INTO study_participants_relationship VALUES(30,25);
  • 它失败,因为在id为值为30(第一列外键约束)的研究中没有行。如果值30确实存在,则第二个约束将启动,因为参与者中没有id为25的行。

  • 列外键约束表外键约束之间没有区别,除了它们的编码位置和方式。

    < / LI>
  • 但是,上述内容并不会阻止您从study_participants_relationship表中删除所有行,因为如果它们被study_participants_relationship表引用,它将阻止您从研究或参与者表中删除一行。

    < / LI>