当前位置: 首页 > 面试题库 >

如何处理相互递归的插入

谷梁建中
2023-03-14
问题内容

我有一个定义相互递归表的模型:

Answer
  questionId QuestionId
  text

Question
  text
  correct AnswerId

要实际插入问题,我需要怎么做?我需要知道什么是正确的答案。但是要插入答案,我需要知道答案是什么。

如果有问题,我正在运行Postgres。

DDL为:

CREATE TABLE answer (
  id integer NOT NULL,                -- answer id
  text character varying NOT NULL,    -- answer text
  question_id bigint NOT NULL         -- question id
);

CREATE TABLE question (
  id integer NOT NULL,                 -- question id
  question character varying NOT NULL, -- question text
  correct bigint NOT NULL,             -- correct answer
  solution character varying NOT NULL  -- solution text
);

ALTER TABLE ONLY answer ALTER COLUMN id SET DEFAULT nextval('answer_id_seq'::regclass);

ALTER TABLE ONLY answer
  ADD CONSTRAINT answer_question_id_fkey FOREIGN KEY (question_id) REFERENCES question(id);

ALTER TABLE ONLY question ALTER COLUMN id SET DEFAULT nextval('question_id_seq'::regclass);
ALTER TABLE ONLY question
  ADD CONSTRAINT question_correct_fkey FOREIGN KEY (correct) REFERENCES answer(id);

问题答案:

如果您使用数据修改CTE在 单个语句中
输入问题和答案,那么您甚至都不需要FK约束。更不用说实际制造(或发声)它们了-
这会贵得多。DEFERRABLE``SET``DEFERRED

资料模型

首先,我清理了您的数据模型:

CREATE TABLE question (
   question_id       serial PRIMARY KEY
 , correct_answer_id int  NOT NULL
 , question          text NOT NULL
 , solution          text NOT NULL
);

CREATE TABLE answer (
   answer_id   serial PRIMARY KEY
 , question_id int  NOT NULL REFERENCES question
 , answer      text NOT NULL
);

ALTER TABLE question ADD CONSTRAINT question_correct_answer_id_fkey
FOREIGN KEY (correct_answer_id) REFERENCES answer(answer_id);
  • 不要使用非描述性的“ id”作为列名。
  • 不要使用基本类型名text作为列名。
  • 为了节省空间,将整数列放在第一位:
    • 在PostgreSQL中计算并节省空间
  • bigint没必要,integer就足够了。
  • 使用serialcolumn简化您的架构定义。
  • 定义主键。PK列是NOT NULL自动的。

解决方案

我委派主键生成到序列(serial列)像它 应该 在大多数数据模型。我们可以使用语句的RETURNING子句获取自动生成的ID
INSERT。但是在这种特殊情况下,我们每个人 需要 两个 ID INSERT,因此我nextval()开始使用其中的一个ID 。

WITH q AS (
   INSERT INTO question (correct_answer_id, question, solution)
   VALUES (nextval('answer_answer_id_seq'), 'How?', 'DEFERRABLE FK & wCTE')
   RETURNING correct_answer_id, question_id
   )
INSERT INTO answer (answer_id, question_id, answer)
SELECT correct_answer_id, question_id, 'Use DEFERRABLE FK & data-modifying CTE'
FROM   q;

知道 序列('answer_answer_id_seq')的名称,因为我查找了它。这是默认名称。如果您不 知道
,请使用以下评论中提供的安全格式@IMSoP:

nextval(pg_get_serial_sequence('answer', 'answer_id'))

DEFERRABLEDEFERRED约束?

每个文档上 SET CONSTRAINTS

IMMEDIATE 在每个语句的末尾检查约束。

我的解决方案是一个 单一的 声明。这就是为什么它可以在两个单独的语句失败的地方工作的原因-是否包装在单个事务中。而且你需要SET CONSTRAINTS ...DEFERRED;像IMSOP第一评论和@Jaaz在他的回答中实现。 但是,请注意免责声明的某些段落:

DEFERRABLE还可以立即检查尚未声明的唯一性和排除约束 。

因此UNIQUEEXCLUDE需要DEFERRALBE使wCTE为他们工作。这包括PRIMARY KEY约束。上的文档CREATE TABLE具有更多详细信息:

非递延唯一性约束

当aUNIQUEPRIMARY KEY约束不可延迟时,无论何时插入或修改一行,PostgreSQL都会立即检查其唯一性。SQL标准指出,唯一性应仅在语句末尾强制执行;否则,请参见参考资料。例如,当一个命令更新多个键值时,这会有所不同。为了获得符合标准的行为,请将约束声明为,DEFERRABLE但不要延迟(即INITIALLY IMMEDIATE)。请注意,这比立即进行唯一性检查要慢得多。



 类似资料:
  • 假设我编写这样的代码: 我如何让Kotlin优化这些相互递归的函数,以便在不抛出StackOverflower错误的情况下运行main?tailrec关键字适用于单函数递归,但没有更复杂的功能。我还看到一个警告,在使用关键字tailrec的地方没有找到尾部调用。也许这对编译器来说太难了?

  • 问题内容: 我有一个应用程序,该应用程序具有一组具有递归关系的数据(使用递归的树状视图。)我尝试了几种通过Angular实现此关系的方法,但似乎都没有一种可行的结果。 这里的想法是,我希望使用一组嵌套列表来呈现此数据,以允许许多(7+)深度级别。为了简化操作(我的实际应用程序使用Restangular),我构建了以下插件: http://plnkr.co/edit/dKT9OvpsMgnxmLwg

  • 问题内容: 假设您有表格和。保存演示文稿并包含基本事件信息(如位置和日期)后,将使用触发器自动创建事件。(由于技术原因,恐怕不可能仅将数据保存在一个位置并使用视图。)此外,在稍后的演示中更改此信息时,触发器也会将更新复制到事件中,像这样: 现在,客户需要它,这样,如果用户更改了 事件中 的信息,它也应该返回到演示。出于明显的原因,我不能相反: 毕竟,这将导致每个触发器彼此触发。我可以做的是在两个表

  • 问题内容: 我正在Ubuntu 14.04上使用Python 3.4进行开发。我试图做递归。在我调用之后,它挂在那里并且永远不会返回。 问题答案: 这是不可能的。所述对象本身不能安全进程之间被共享,所以相同的池不能在两者中使用和。即使您 可以 执行此操作,也很快会导致挂起,因为您的池仅限于并发工作程序。一旦开始递归地创建更多的工作人员,您最终将获得比工作人员更多的工作量,这将永远无法完成。正在运行

  • 流程互通是指流程之间的数据交换。 有必要在进程之间交换数据以开发并行应用程序。 下图显示了多个子进程之间同步的各种通信机制 - 各种沟通机制 在本节中,我们将了解各种通信机制。 机制如下所述 - Queues 队列可以与多进程程序一起使用。 multiprocessing模块的Queue类与Queue.Queue类相似。 因此,可以使用相同的API。 Multiprocessing .Queue为

  • 递归互斥量(Recursive Mutexes)是互斥量的一个特例,与互斥量基本完全相同,除了: 递归互斥量可以由拥有者多次获取,但是也要求拥有者释放相同次数。比如,一个递归互斥量被获取了5次,那么同样需要释放5次。