返回使用子查询的插入行的ID

时间:2014-02-26 17:33:58

标签: sql oracle stored-procedures

又一个sql(oracle)问题。

我正在尝试返回插入行的ID,但是有一个问题。插入使用子查询。

create or replace procedure NEW_FORECAST_PROFILE (CA_ID IN NUMBER, FP_ID OUT NUMBER)

BEGIN
  INSERT INTO FORECAST_PROFILE(
    NAME,
    COMPANY_ACCOUNT_ID
  )

  SELECT
    TO_CHAR(SYSDATE, 'MON-DD-yyyy HH:MM AM') AS NAME,
    COMPANY_ACCOUNT_ID
  FROM MASTER_DEFAULTS
  WHERE COMPANY_ACCOUNT_ID = CA_ID

  RETURNING FORECAST_PROFILE_ID INTO FP_ID;

END;

我正在尝试做什么:

1)在一个表中查找一行并将其复制到另一个表中。

2)返回新行的ID(FORECAST_PROFILE_ID),该ID由触发/序列组合自动递增。

我愿意接受各种想法。这不起作用,因为我猜测sql解析器期望返回多个ID。

我发现了一些接近但我需要转换为oracle语法:

DECLARE @inserted_ids TABLE ([id] INT);

INSERT INTO [dbo].[some_table] ([col1],[col2],[col3],[col4],[col5],[col6])
OUTPUT INSERTED.[id] INTO @inserted_ids
VALUES (@col1,@col2,@col3,@col4,@col5,@col6)

**更新** 解决问题的一种(坏)方法是获取用于生成列的序列的当前值。但是,如果有多个用户更新表格,我认为这会遇到问题。

FP_ID := FORECAST_PROFILES_SEQ.CURRVAL;

1 个答案:

答案 0 :(得分:2)

这里的问题是你的select 可能会返回多行。也许不是现在,但是谁知道将来会对你的架构进行屠宰。 Oracle无需检查company_account_id是否具有唯一约束,并且约束是否有效并已启用。

我会按如下方式重新组织声明:

FOR r_profile IN (
    SELECT
        TO_CHAR(SYSDATE, 'MON-DD-yyyy HH:MM AM') AS NAME,
        COMPANY_ACCOUNT_ID
    FROM MASTER_DEFAULTS
    WHERE COMPANY_ACCOUNT_ID = CA_ID
)
LOOP

  INSERT INTO FORECAST_PROFILE (
      NAME,
      COMPANY_ACCOUNT_ID
  ) VALUES (
      r_profile.NAME,
      r_profile.COMPANY_ACCOUNT_ID
  ) RETURNING
      FORECAST_PROFILE_ID INTO L_FP_ID
  ;
END;

FP_ID := L_FP_ID;

您只需要声明L_FP_ID局部变量,尽管您可以完全跳过它并使用FP_ID。缺点是,如果系统发生了更改,以至于查询返回多行,则只返回最后一个ID。