【问题标题】:UPDATE or INSERT INTO is not working in procedure?UPDATE 或 INSERT INTO 在程序中不起作用?
【发布时间】:2016-11-02 09:53:11
【问题描述】:

Attendance

EMPL_KODE |EMPL_NAME  |DATE_IN    |TIME_IN |TIME_OUT|TOTAL_MIN |TOTAL_HOUR
--------------------------------------------------------------------------
    001   | Michel    |25.04.2016 |06:50   |15:40   |NULL      |NULL
    002   | Clara     |25.04.2016 |06:15   |15:43   |NULL      |NULL
    003   | Rafael    |25.04.2016 |06:25   |15:45   |NULL      |NULL
    001   | Michel    |26.04.2016 |06:23   |15:42   |NULL      |NULL
    002   | Clara     |26.04.2016 |06:10   |15:41   |NULL      |NULL
    003   | Rafael    |26.04.2016 |06:30   |15:42   |NULL      |NULL
    001   | Michel    |27.04.2016 |06:33   |15:42   |NULL      |NULL
    002   | Clara     |27.04.2016 |06:54   |15:44   |NULL      |NULL
    003   | Rafael    |27.04.2016 |07:00   |15:45   |NULL      |NULL

我已经成功地使用以下语法创建了为列 TOTAL_MINTOTAL_HOUR 自动插入值的过程:

SET TERM ^ ;
ALTER PROCEDURE UPDATEEMPLOYEES
AS
DECLARE VARIABLE EMPL_KODE CHAR(5);
DECLARE VARIABLE EMPL_NAME VARCHAR (25);
DECLARE VARIABLE TIME_IN TIMESTAMP;
DECLARE VARIABLE TIME_OUT TIMESTAMP;
DECLARE VARIABLE TOTAL_MINUTES INTEGER;
DECLARE VARIABLE TOTAL_HOURS FLOAT;

BEGIN 
FOR SELECT e.EMPL_KODE, e.EMPL_NAME,
       CAST(a.DATE_IN + a.TIME_IN AS TIMESTAMP),
       CAST(a.DATE_IN + a.TIME_OUT AS TIMESTAMP),
       DATEDIFF(MINUTE,a.TIME_IN,a.TIME_OUT),
       DATEDIFF(HOUR,a.TIME_IN,a.TIME_OUT)
       FROM EMPLOYEE e
       JOIN ATTENDANCE a
       ON e.EMPL_KODE=a.EMPL_KODE

INTO :EMPL_KODE,:EMPL_NAME,:TIME_IN,:TIME_OUT,TOTAL_MINUTES,TOTAL_HOURS
DO
       UPDATE ATTENDANCE a
       set a.TOTAL_MINUTES=:TOTAL_MINUTES,
       a.TOTAL_HOURS=:TOTAL_HOURS
       WHERE a.EMPL_KODE=:EMPL_KODE;

end^
SET TERM ; ^

但是,问题是如何直接使用 UPDATEINSERT INTO 编写语法?我已经尝试过,但仍然无法正常工作。

我编写的代码与 Firebird 指令相同。

   UPDATE OR INSERT INTO
   {tablename | viewname} [(<columns>)]
   VALUES (<values>)
   [MATCHING (<columns>)]
   [RETURNING <values> [INTO <variables>]]

<columns>      ::=  colname  [, colname  ...]
<values>       ::=  value    [, value    ...]
<variables>    ::=  :varname [, :varname ...]

这是我的代码:

我不写Returning,因为我不明白它是什么。

SET TERM ^ ;
ALTER PROCEDURE BLABLA(
    TOTAL_M INTEGER,
    TOTAL_H FLOAT)
AS
BEGIN 
    UPDATE or INSERT INTO ATTENDANCE (TOTAL_MINUTES,TOTAL_HOURS)
    VALUES (:TOTAL_M,:TOTAL_H)
    MATCHING (EMPL_KODE);
end^
SET TERM ; ^

在我提交语句后,它显示错误消息:

UPDATE OR INSERT 字段列表不匹配 MATCHING 子句

我该怎么办?

【问题讨论】:

  • firebird 还有一个 MERGE INTO DML 声明用于 upserts。
  • 查看 ain 的直接问题的答案,但是根据您在问题开始时显示的表格,我认为您当前的 update or insert 不够精确;我希望列列表、值列表和匹配列表也包括列 DATE_IN

标签: sql firebird flamerobin


【解决方案1】:

我认为问题在于您有 MATCHING (EMPL_KODE) 但您没有在值列表中列出 EMPL_KODE 列 - 您希望引擎如何确定要更新哪些行?尝试类似:

SET TERM ^ ;
ALTER PROCEDURE BLABLA(
    E_KODE CHAR(5),
    TOTAL_M INTEGER,
    TOTAL_H FLOAT)
AS
BEGIN 
    UPDATE or INSERT INTO ATTENDANCE (TOTAL_MINUTES,TOTAL_HOURS, EMPL_KODE)
    VALUES (:TOTAL_M,:TOTAL_H, :E_KODE)
    MATCHING (EMPL_KODE);
end^
SET TERM ; ^

【讨论】:

    【解决方案2】:

    终于,我从这个http://www.firebirdfaq.org/faq336得到了答案

    SET TERM ^ ;
    ALTER PROCEDURE UPDATEEMPLOYEEES
    AS
    begin
    UPDATE ATTANDENCE
    SET TOTAL_MINUTES=DATEDIFF(MINUTE,TIME_IN,TIME_OUT),
        TOTAL_HOURS=DATEDIFF(MINUTE,TIME_IN,TIME_OUT)/60.0;
    END^
    SET TERM ; ^
    

    【讨论】:

      猜你喜欢
      • 2017-12-06
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多