我想在其他表的一个表中显示外键,但我得到外键错误错误

时间:2018-03-23 01:19:25

标签: java database sqlite netbeans

我是SQL的新手,我希望 contracts_tb (下面的查询详情)是显示和链接引用的外来ID键:

med_idref (referred from med_id (INTEGER), PRIMARY KEY o mediaadv_tb),
mediatitle_ref (title (TEXT), mediaadv_tb),
       mediatype_red (mtype (TEXT), mediaadv_tb),
cus_idref (cus_id (INTEGER),PRIMARY KEY of customer_tb), 
cus_companyref (referred from company (TEXT), in customer_tb)

全部链接并显示到 contracts_tb 。当我从 mediaadv_tb customer_tb 添加/替换值时,我遇到了这个问题:

  

foreignkey mismatch

另外,我是否必须制作或分配父表?

查询:

DROP TABLE IF EXISTS customer_tb;    
CREATE TABLE IF NOT EXISTS customer_tb (
    cus_id INTEGER PRIMARY KEY, 
    company TEXT, 
    firstname TEXT, 
    middlename TEXT, 
    lastname TEXT, 
    gender TEXT, 
    dob TEXT, 
    dateregistered TEXT, 
    contactno  TEXT, 
    emailaddress TEXT, 
    description TEXT, 
    refpic INTEGER,
    cuspic BLOB
);


DROP TABLE IF EXISTS mediaadv_tb;
CREATE TABLE IF NOT EXISTS mediaadv_tb (
    med_id INTEGER PRIMARY KEY, 
    mtype TEXT,
    duration TEXT,
    title TEXT, 
    dateadded TEXT,
    desription TEXT,
    previewimg BLOB, 
    filepath TEXT
);


DROP TABLE IF EXISTS contracts_tb;
CREATE TABLE IF NOT EXISTS contracts_tb (
    contract_id INTEGER PRIMARY KEY, 
    customer_idref INTEGER REFERENCES customer_tb (cus_id),
    media_idref INTEGER REFERENCES mediaadv_tb (med_id),
    media_typeref TEXT REFERENCES mediaadv_tb(mtype),
    media_titleref TEXT REFERENCES mediaadv_tb (title), 
    status TEXT, 
    priority TEXT, 
    dateadded TEXT, 
    dateexpiration TEXT, 
    amountpaid REAL, 
    arearofcoverage TEXT 

);

错误: -

enter image description here

contracts_tb

enter image description here

mediaadv_tb

enter image description here

1 个答案:

答案 0 :(得分:2)

我认为您的问题是因为定义的外键引用 media_typeref media_titleref 列无效,因为它们没有或属于UNIQUE索引(无索引)。 SQLite Foreign Key Support - 3. Required and Suggested Database Indexes

引用的 id 列,因为它们是INTEGER PRIMARY KEY,是隐式UNIQUE索引。

此外,甚至不需要两列(typeref和titleref),因为media_idref列将用于标识引用,因此将保存相应的值。将这些值复制到合同表中将违反规范化,甚至可能造成严重的麻烦(例如,如果值发生变化,您必须找到所有其他用途并更改它们)。

因此我建议使用以下方法创建 contracts_tb : -

DROP TABLE IF EXISTS contracts_tb;
CREATE TABLE IF NOT EXISTS contracts_tb (
    contract_id INTEGER PRIMARY KEY, 
    customer_idref INTEGER REFERENCES customer_tb (cus_id),
    media_idref INTEGER REFERENCES mediaadv_tb (med_id),
    status TEXT, 
    priority TEXT, 
    dateadded TEXT, 
    dateexpiration TEXT, 
    amountpaid REAL, 
    arearofcoverage TEXT 
);

评论: -

  

我正在制作的是Java NetBeans SQLite数据库程序,其中包括   使用合同框架,那里有一个新的合同   将是一个组合框,限制用户只放置现有的   contract_tb中引用的id或名称随后提供   选择。先生可以吗?

更具体地说: -

假设您有客户 Fred,Bert和Harry(分别为ID 1,2和3)。并且你有 mediaadv 的M1,M2和M3(id为10,11和12(不是1,2和3来帮助区分mediaadv和客户))。

此外,我将假设建议的contract_tb表而不是问题中的原始表(即按建议删除2列)

在插入新合同时,您会提供客户的列表(组合框),例如

佛瑞德

伯特

哈利

(此列表可以通过以下查询生成: -

  • SELECT cus_id,firstname FROM customer_tb;即所有现有客户

  • 如果您想要Fred James Bloggs,那么您可以使用: -

    • SELECT cus_id,firstname||' '||middlename||'lastname' AS fullname FROM customer_tb;

同样,可以从查询中生成现有mediaadv的列表,例如: -

  • SELECT med_id, description FROM mediaadv_tb;例如

所以组合框会有: -

M1

M2

M3

现在,如果合同是针对Bert(id 2 )和M1(id 10 ),那么您构建的SQL类似于: -

INSERT INTO contracts_tb VALUES(null,2,10,'the_status','the_priority','yyyy-mm-dd','yyyy-mm-dd',500,'the_coverage');

  • 第一个值为空,即没有值,因此contract_id是将生成的rowid的别名。
  • 2是客户的ID(因此,为什么cus_id在查询中,因为您需要id,因为它是您要存储的值)
  • 10是mediaadv的id(再次为什么med_id在查询中,因为你需要id,因为它是你要存储的值)。
  • 其他值是他们应该的。

  • 注意上面INSERT的使用要求给出所有列。您可以通过指定列的列表来跳过列,例如INSERT INTO contracts_tb (customer_idref,media_idref) VALUES(2,10);

当cus_id为2(Bert)的客户存在时,customer_idref是customer_tb中现有id的约束是好/符合​​且没有冲突。

同样,因为mediaadv_tb中有一行med_id为10,所以这个约束很好/符合并且没有冲突。

但是说SQL是: -

INSERT INTO contracts_tb VALUES(null,2,100,'the_status','the_priority','yyyy-mm-dd','yyyy-mm-dd',500,'the_coverage');

然后因为没有med_id为100的约束,说media_idref必须在mediaadv_tb,列med_id中引用值100(在本例中),那么将不会满足约束并且插入将失败。

再次,是的,我相信你想要的是可行的。

注意外键只是一个约束,它不会绑定/关联列或连接表。