为什么这个get-or-create函数似乎永远不会插入?

时间:2014-01-20 09:51:57

标签: oracle plsql

我正在编写一个函数,用于批量导入数据到我们的组织结构图中。它似乎适用于检索已存在的条目,但是当一个条目尚不存在时,它应该插入,提交并返回重新尝试的结果(以便获得自动生成的ID),它总是返回NULL

我确定我在这里做错了什么,但是什么?帮助赞赏。

注意:如果没有指定,则会有DEPT_ID填充前插入触发器。如果手动执行insert语句,则可以正常工作。

CREATE TABLE DEPTS 
(    
  "DEPT_ID" VARCHAR2(10 BYTE), 
  "HEADER_ID" VARCHAR2(10 BYTE), 
  "COMMENTS" VARCHAR2(100 BYTE), 
  "CATEGORY" VARCHAR2(2 BYTE)
);

CREATE OR REPLACE FUNCTION get_or_make_unit(
, in_cat VARCHAR2
, in_cmt VARCHAR2
, in_hdr VARCHAR2 DEFAULT NULL
) RETURN VARCHAR2 AS
  unit_id VARCHAR2(10);
BEGIN
  unit_id := NULL;

  IF in_hdr IS NULL THEN
    SELECT dept_id
      INTO unit_id
      FROM depts unit
     WHERE unit.category = in_cat
       AND unit.comments = in_cmt
       AND unit.header_id IS NULL;
  ELSE
    SELECT dept_id
      INTO unit_id
      FROM depts unit
     WHERE unit.category = in_cat
       AND unit.comments = in_cmt
     AND unit.header_id = in_hdr;
  END IF;

  IF unit_id IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('Inserting!');
    INSERT INTO depts (
      header_id
    , comments
    , category
    ) VALUES (
      in_hdr
    , in_cmt
    , in_cat);
    COMMIT;
    unit_id := get_or_make_unit(in_cat, in_cmt, in_hdr);
    RETURN unit_id;
  ELSE
    DBMS_OUTPUT.PUT_LINE('Not inserting!');
    RETURN unit_id;
  END IF;
END get_or_make_unit;

触发器:

CREATE OR REPLACE TRIGGER HRD.DEPTS_BIR
BEFORE INSERT
ON HRD.DEPTS
FOR EACH ROW
DECLARE
  JML NUMBER;
BEGIN
  SELECT SEQ_DEPT_ID.NEXTVAL INTO JML FROM DUAL;
  :NEW.DEPT_ID:='D'||to_char(JML);
END DEPTS_BIR; 

实施例

这有效:

INSERT INTO depts (
      header_id
    , comments
    , category
    ) VALUES (
      'D532'
    , 'ACCOUNTING'
    , '2');
COMMIT;

SELECT get_or_make_unit('2', 'ACCOUNTING', 'D532') FROM DUAL;
=> 'D533'

这不是:

SELECT get_or_make_unit('2', 'NEW DEPT', 'D532') FROM DUAL;
=> NULL

3 个答案:

答案 0 :(得分:1)

而不是:

INSERT INTO depts (
      header_id
    , comments
    , category
    ) VALUES (
      in_hdr
    , in_cmt
    , in_cat);
COMMIT;
unit_id := get_or_make_unit(in_cat, in_cmt, in_hdr);

使用RETURNING INTO

INSERT INTO depts (
      header_id
    , comments
    , category
    ) VALUES (
      in_hdr
    , in_cmt
    , in_cat) RETURNING dept_id INTO unit_id;
COMMIT;

我认为递归调用不是最好的方法,但如果你严格使用它,那么请发布前面提到的插入触发器的定义。

UPDATE:您无法从SQL语句调用包含DML操作的函数。有关详细信息,请see this answer。正确呼叫的示例:

DECLARE
 unit_id varchar2(32);
BEGIN
 unit_id := get_or_make_unit('2', 'NEW DEPT', 'D532');
 dbms_output.put_line(unit_id);
END;

UPDATE2:此外,您还需要捕获在使用不存在的组合调用函数时引发的NO_DATA_FOUND异常。以下是示例:

CREATE OR REPLACE FUNCTION get_or_make_unit(in_cat VARCHAR2,
                                            in_cmt VARCHAR2,
                                            in_hdr VARCHAR2 DEFAULT NULL)
  RETURN VARCHAR2 AS
  unit_id VARCHAR2(10);
BEGIN
  unit_id := NULL;
  IF in_hdr IS NULL THEN
    SELECT dept_id
      INTO unit_id
      FROM depts unit
     WHERE unit.category = in_cat
       AND unit.comments = in_cmt
       AND unit.header_id IS NULL;
  ELSE
    SELECT dept_id
      INTO unit_id
      FROM depts unit
     WHERE unit.category = in_cat
       AND unit.comments = in_cmt
       AND unit.header_id = in_hdr;
  END IF;
  DBMS_OUTPUT.PUT_LINE('Not inserting!');
  RETURN unit_id;
exception
  when NO_DATA_FOUND then
    DBMS_OUTPUT.PUT_LINE('Inserting!');
    INSERT INTO depts
      (header_id, comments, category)
    VALUES
      (in_hdr, in_cmt, in_cat)
    returning dept_id into unit_id;
    COMMIT;
    RETURN unit_id;
END get_or_make_unit;

答案 1 :(得分:0)

您对get_or_make_unit的调用似乎缺少第一个参数。

答案 2 :(得分:0)

INSERT INTO depts (
      header_id
    , comments
    , category
    ) VALUES (
      in_hdr
    , in_cmt
    , in_cat);

此代码未在depts表的dept_id中插入任何内容。这就是你得到空的原因