【问题标题】:Relating two tables关联两个表
【发布时间】:2016-03-31 14:32:10
【问题描述】:

我创建了带有列(id 作为主键和名称)的表 T1 和带有列(id 作为主键,名称,t_id 作为外键引用 T1(id))的 T2。我从 Windows 窗体的输入中插入了一些值。查询 SELECT * FROM T2 后;使用 isql,由于创建了关系,外键列中的所有值都为空,而不是重复 T1(id) 中的值。它们是我遗漏或需要添加的东西吗?两个表的主键都是自动递增的。

【问题讨论】:

  • 显示T2表的insert查询
  • INSERT INTO T2(name) VALUES (textbox.Text) ;h主键(id)由生成器自动递增。
  • 您需要为t_id 列插入数据,否则它将是NULLINSERT INTO T2(name,t_id) VALUES (textbox.Text,'someval')
  • TI(id) 是自动递增的。有没有办法获取最后插入的值,保存并传递它?
  • 是的,你需要使用INSERT ... RETURNING ...

标签: sql firebird


【解决方案1】:

您混淆了自动递增键和关系的使用。

自动递增的键(或通常说的字段)只会在您在键的表上插入新记录时为您提供帮助。但是,当您插入一条引用另一个表中的记录的新记录时,您必须使用外键字段指定该记录。或者在您的情况下,在 T2 中插入“名称”的用户必须说明 T1 上的哪一条记录 T2 中的“名称”正在引用。

您对关系的困惑在于,您认为已建立的关系会自动强制使用该值。但这种关系只是强制执行值的验证。因此,T2 中的字段 t_id 不会自动使用 T1 的最后一条记录的值。但是如果你尝试在字段 t_id 中插入一个 T1 中不存在的值,则关系不会让你这样做。

那么,回答您的问题,您遗漏了什么,需要添加什么? 您省略了在 T2 表的 t_id 字段中插入值的部分代码。

让我试着用一个更常见的例子来解释。

最常见的情况是应用程序首先插入 T1 记录,然后当用户插入 T2 时,应用程序为用户提供了一种方法来选择他的 T2 记录引用的 T1 记录。

假设 T1 是 publishers 表,T2 是 book 表。用户插入一个出版商,当它插入一本书时,它可以选择哪一个出版商出版这本书。

【讨论】:

    【解决方案2】:

    在使用表 CUSTOMERS 上的 Event BeforeInsert 创建表时,客户的字段“ID”默认为 AUTOINCREMENT。看看

    CREATE TRIGGER nametrigger FOR nametable 在插入位置 0 之前激活 作为 开始 如果(NEW.ID 为空)然后开始 NEW.ID = GEN_ID(GEN_PK_ID, 1); 结束

    结束

    现在客户中的一项新记录

    插入客户(客户姓名、联系人姓名、地址、城市、邮政编码、国家/地区) 值('红衣主教'、'Tom B. Erichsen'、'Skagen 21'、'斯塔万格'、'4006'、'挪威');

    然后 ID 将自动成为从 1 到最后一个整数或 smallint 或 bigint 的一个序列号,正如您在创建表中定义的那样(请注意 ID 字段不包含在 FIELDS 和 VALUES 中),因为 TRIGGER

    现在您可以使用数据集(obj)选项来链接表 MATER 和 DETAIL,请参见帮助 delphi

    或者在 SQL 中你可以使用 PARAMS FIELDS

    稍后在 MASTER 表中插入一条新记录试试...

    INSERT INTO xTable2 (IDcustomersField, ..., ..., ...., ....) 值 (:IDcustomersField, ..., ..., ...., ....);

    xTable2 也可以使用一个字段 ID(主键)自增。此表中删除或更新文件时的帮助

    然后您可以使用 :IDcustomersField 在表格详细信息中说出值 xQuery.PARAM( 0 ).value 或 xQuery.PARAMBYNAME( IDcustomersField).value (这里我以 Query obj 为例)

    您可以在代码中使用带有 DATASOURCE 的示例来说明 IDcustomersField 的值

    可以使用 SQL 中的事件

    可以使用 SQL 中的过程

    别忘了

    您必须在两个表之间创建关系(主表中的 REFERENCIAL INTEGRITY 和 PRIMARY KEY)NOT NULL FOR TWO FIELDS ON TABLES

    我相信我理解我糟糕的解释(我不会说英语

    【讨论】:

      【解决方案3】:

      在从主表 T1 获取 ID 值后,您需要手动插入 t_id 的值。 根据您在数据库中的逻辑,您还可以使用触发器或存储过程。向我们提供有关插入后您希望在 T2 中的 NAME 字段中具有哪些值的更多信息?它们是与 T1 重复还是独立于 T1? 如果 T1.NAME=T2.NAME,您可以使用触发器自动执行该过程

      CREATE OR ALTER TRIGGER TR_T1_AI0 FOR T1
      ACTIVE AFTER INSERT POSITION 0
      AS
      BEGIN
        INSERT INTO T2(NAME, T_ID) 
        VALUES (NEW.NAME, NEW.ID);
      END
      

      如果 T2.NAME 的值与 T1.NAME 不同,您可以使用带有两个名称的参数的存储过程:

      CREATE ORA ALTER PROCEDURE XXXX(
        P_NAME_T1 TYPE OF T1.NAME,
        P_NAME_T2 TYPE OF T2.NAME)
      AS
      DECLARE VARIABLE L_ID TYPE OF T1.ID;
      BEGIN
        INSERT INTO T1(NAME)
        VALUES (:p_NAME_T1)
        RETURNING ID INTO:L_ID;   
      
        INSERT INTO T2(NAME, T_ID)
        VALUES (:P_NAME_T2, :l_ID);
      END
      

      如果程序支持返回语法,您可以直接在程序中使用存储过程中的两个语句。如果没有,您需要使用 SELECT NEXT VALUE FOR GENERATOR_FOR_T1 FROM RDB$DATABASE; 进行额外查询,并在两个 INSERT 语句中使用从它返回的值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-01
        • 2019-04-14
        • 1970-01-01
        • 1970-01-01
        • 2023-03-30
        • 2019-06-23
        • 1970-01-01
        相关资源
        最近更新 更多