如何在Oracle SQL中使用序列加载分层表

huangapple go评论57阅读模式
英文:

How to load a hierarchical table using a sequence in Oracle SQL

问题

如果我有一个层次表:TREE(ID,PARENT_ID,NAME)

如何在SQL中使用序列加载它?
在PLSQL中,我们可以使用变量等,但我想知道是否可以在SQL中完成。

这显然不起作用,它在第2行失败,因为ID = PARENT_ID,而且我有一个检查约束来防止这种情况。

insert into tree (TREE_SEQ.NEXTVAL, NULL, 'root');
insert into tree (TREE_SEQ.CURRVAL, TREE_SEQ.NEXTVAL, 'branch');

这个方法可以工作,但我对并发性有一些担忧。
它还假设序列是使用INCREMENT BY 1定义的。

insert into tree (TREE_SEQ.NEXTVAL, NULL, 'root');
insert into tree (TREE_SEQ.NEXTVAL, TREE_SEQ.CURRVAL - 1, 'branch');
英文:

If I have a hierarchical table : TREE (ID, PARENT_ID, NAME)

How can this be loaded in sql using a sequence?
In PLSQL we could use variables etc. but I'm wondering if it can be done in SQL.

This obviously won't work, it fails on row 2 because ID = PARENT_ID and I have a check constraint preventing it.

insert into tree (TREE_SEQ.NEXTVAL, NULL, 'root');
insert into tree (TREE_SEQ.CURRVAL, TREE_SEQ.NEXTVAL, 'branch');

This works, but I have concerns about concurrency.
It also assumes that the sequence is defined with INCREMENT BY 1

insert into tree (TREE_SEQ.NEXTVAL, NULL, 'root');
insert into tree (TREE_SEQ.NEXTVAL, TREE_SEQ.CURRVAL - 1, 'branch');

答案1

得分: 1

你应该只使用PL/SQL:

DECLARE
  v_id tree.id%TYPE;
BEGIN
  INSERT INTO tree (ID, PARENT_ID, NAME)
  VALUES (TREE_SEQ.NEXTVAL, NULL, 'root')
  RETURNING id INTO v_id;

  INSERT INTO tree (ID, PARENT_ID, NAME)
  VALUES (TREE_SEQ.NEXTVAL, v_id, 'branch');
END;
/

然后,根据以下设置:

CREATE TABLE TREE (
  ID        NUMBER PRIMARY KEY,
  PARENT_ID REFERENCES tree(id),
  NAME      VARCHAR2(10)
);

CREATE SEQUENCE tree_seq;

然后在PL/SQL块之后,表包含以下内容:

ID PARENT_ID NAME
1 null root
2 1 branch

然而,如果你创建一个包装序列的函数:

CREATE FUNCTION get_tree_sequence RETURN TREE.ID%TYPE
IS
BEGIN
  RETURN TREE_SEQ.NEXTVAL;
END;
/

然后你可以在SQL语句中使用它:

INSERT INTO tree (ID, PARENT_ID, NAME)
SELECT id,
       LAG(id) OVER (ORDER BY ROWNUM),
       CASE ROWNUM WHEN 1 THEN 'root' ELSE 'branch' END
FROM   (
  SELECT get_tree_sequence() AS id
  FROM   DUAL
  CONNECT BY LEVEL <= 2
);

然后表现在包含以下内容:

ID PARENT_ID NAME
1 null root
2 1 branch
3 null root
4 3 branch

fiddle

英文:

You ought to just use PL/SQL:

DECLARE
  v_id tree.id%TYPE;
BEGIN
  INSERT INTO tree (ID, PARENT_ID, NAME)
  VALUES (TREE_SEQ.NEXTVAL, NULL, 'root')
  RETURNING id INTO v_id;

  INSERT INTO tree (ID, PARENT_ID, NAME)
  VALUES (TREE_SEQ.NEXTVAL, v_id, 'branch');
END;
/

Which, given the setup:

CREATE TABLE TREE (
  ID        NUMBER PRIMARY KEY,
  PARENT_ID REFERENCES tree(id),
  NAME      VARCHAR2(10)
);

CREATE SEQUENCE tree_seq;

Then after the PL/SQL block, the table contains:

ID PARENT_ID NAME
1 null root
2 1 branch

However, if you create a function to wrap the sequence:

CREATE FUNCTION get_tree_sequence RETURN TREE.ID%TYPE
IS
BEGIN
  RETURN TREE_SEQ.NEXTVAL;
END;
/

Then you can use it in an SQL statement:

INSERT INTO tree (ID, PARENT_ID, NAME)
SELECT id,
       LAG(id) OVER (ORDER BY ROWNUM),
       CASE ROWNUM WHEN 1 THEN 'root' ELSE 'branch' END
FROM   (
  SELECT get_tree_sequence() AS id
  FROM   DUAL
  CONNECT BY LEVEL <= 2
);

Then the table now contains:

ID PARENT_ID NAME
1 null root
2 1 branch
3 null root
4 3 branch

fiddle

huangapple
  • 本文由 发表于 2023年7月13日 22:14:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76680372.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定