Search code examples
sqlfirebirdfirebird2.5ibexpert

How to use a generator in my execute statement in a stored procedure?


I'm trying to create a simple stored procedure in IBExpert for a Firebird 2.5 database. I'm having trouble to work with generators though. I think I've created a valid generator & trigger. But I don't know how to apply those in my execute statement.

Table:

ID            BIGINT NOT NULL,
DATUM         INTEGER,
KOSTENST      INTEGER,
KUNDENNUMMER  INTEGER,
DISPONENT     CHAR(5),
KONTAKTART    CHAR(2)

Trigger:

CREATE OR ALTER trigger kontakte_erw_id_bi for kontakte_erw_id
active before insert position 0
AS
BEGIN
if (NEW.ID is NULL) then NEW.ID = GEN_ID(ID_KONTAKTE, 1);
END 

Generator:

CREATE SEQUENCE ID_KONTAKTE;
ALTER SEQUENCE ID_KONTAKTE RESTART WITH 0;

Procedure statement (I think the problem lays here? How to I address the trigger to fill the ID column?):

for execute statement('
  SELECT
        KONTAKTE.DATUM,
        KUNDEN.KOSTENST,
        KUNDEN.KUNDENNR,
        KONTAKTE.DISPONENT,
        KONTAKTE.KONTAKTART

FROM KONTAKTE
INNER JOIN KUNDEN ON KONTAKTE.KUNDENNR = KUNDEN.KUNDENNR

')
          on external 'db'
          as user 'xxx' password xxx

          into :XDATUM, :XKOSTENST, :XKUNDENNUMMER, :XDISPONENT, :XKONTAKTART

  do
  begin

    execute statement

    ('update or insert into KONTAKTE_ERW_ID (DATUM, KOSTENST, KUNDENNUMMER, DISPONENT, KONTAKTART)

      values

    (:DATUM, :KOSTENST, :KUNDENNUMMER, :DISPONENT, :KONTAKTART)')


   (DATUM:= XDATUM, KOSTENST := XKOSTENST, KUNDENNUMMER := XKUNDENNUMMER, DISPONENT := XDISPONENT, KONTAKTART := XKONTAKTART)

        on external 'db'
        as user 'xxx' password xxx;

  end

This is the error I get when trying to populate the chart:

336003099 : UPDATE OR INSERT field list does not match primary key of table KONTAKTE_ERW_ID
Statement : update or insert into KONTAKTE_ERW_ID (DATUM, KOSTENST, KUNDENNUMMER, DISPONENT, KONTAKTART)

      values

    (?, ?, ?, ?, ?)

Solution

  • Your problem is that to be able to use UPDATE OR INSERT, Firebird needs to know when a row already exists. For this it either uses the primary key, or - when provided - the MATCHING clause.

    In your statement you aren't providing the primary key, but also no MATCHING clause, so Firebird cannot decided if there is a row to update or if it should insert.

    In your situation, including the primary key in the statement does not seem to be an option (or you need to apply a scheme for generating identifiers that can be unique across different databases), so your only option is to use the MATCHING clause. However, looking at your columns, I don't immediately see something that could be considered unique.