Firebird и съхранени процедури: ако съществува, значи друго

Опитвам се да създам съхранена процедура за firebird 2.1 (това е версията, която ще се използва), но малко се забивам, така че всяка помощ е благодарна. Окончателната версия трябва да сравни 4 стойности спрямо таблицата и да извлече или основния идентификатор, ако стойността съществува, или да създаде нов запис в таблицата и да върне новия първичен идентификатор.

Но се забивам само с едно търсене на стойност и то дори още не използва променливата.

SET TERM ^ ;

CREATE PROCEDURE TESTSP 
 ( A Varchar(64) ) 
RETURNS 
 ( RESULT Integer )
AS 

BEGIN
IF (EXISTS (SELECT PRIMARYID FROM TABLENAME WHERE FIELD = 'Some string')) then
    SELECT PRIMARYID FROM TABLENAME WHERE FIELD = 'Some string' into :primaryid;
    result = PRIMARYID;
ELSE 
    INSERT INTO TABLENAME (FIELD) VALUES ('Some string');
    result = gen_id(GEN_TABLEID, 0);
END^

SET TERM ; ^

Получавам "Token unknown" за командата Else.

Актуализация след отговори: Сега искам да използвам 4-те променливи и да върна 4-те резултата. Мисля, че имам нужда от for цикъл, за да направя това, но с firebird функцията for означава нещо друго. И така, какъв би бил пътят?

SET TERM ^ ;

CREATE PROCEDURE TESTSP 
 ( value1 Varchar(64) ) 
RETURNS 
 ( RESULT1 Integer )
AS 

BEGIN
    IF (EXISTS (SELECT PRIMARYID FROM TABLENAME WHERE FIELD = :value1)) then
        SELECT PRIMARYID FROM TABLENAME WHERE FIELD = value1 into :result1;
    ELSE BEGIN
        result1 = gen_id(GEN_TABLEID, 1);
        INSERT INTO TABLENAME (PRIMARYID, FIELD) VALUES (:result1, :value1);
    END
    suspend;
END^

SET TERM ; ^

person Giancarlo    schedule 30.12.2013    source източник


Отговори (3)


Както Тико вече отговори, трябва да използвате begin / end, за да групирате множество изявления в then / else част. Грешката в колоната PRIMARYID е неизвестна е, защото се позовавате на нея, без да сте декларирали локална променлива за нея. Опитайте тази:

CREATE PROCEDURE TESTSP ( A Varchar(64) ) 
RETURNS ( RESULT Integer )
AS 
BEGIN
  -- initialize the result
  Result = NULL;
  -- check is the string already in table
  SELECT PRIMARYID FROM TABLENAME WHERE FIELD = 'Some string' into :Result;
  IF (Result is NULL) then
    INSERT INTO TABLENAME(PRIMARYID, FIELD) VALUES(gen_id(GEN_TABLEID, 1), 'Some string') RETURNING PRIMARYID INTO :Result;
END^
person ain    schedule 31.12.2013
comment
Здравейте, това работи, но когато се опитвате да използвате променливата A (или value1) (value1 Varchar(64)) в където Field = value1 into :Result; Отново получавам колоната неизвестен. Ако поставя в двойни кавички стойността1, това ще означава буквално. И така, как бих могъл да използвам променливата? - person Giancarlo; 31.12.2013
comment
Поставете префикс с двоеточие, така отделяте параметри/променливи от колони в SQL изрази в PSQL, т.е. :A или :value1 - person ain; 31.12.2013
comment
Здравейте, тази работа за създаването на SP. Но когато го изпълнявате с фламеробин като: SELECT p.RESULT FROM TESTSP(VALUE1) p дава неизвестна колона VALUE1. И бих искал да завъртя тази функция 4 пъти за 4 стойности и да получа 4 резултата. Имате ли съвет как да се справя с това? Актуализирах оригиналната си публикация с всички отговори, за да съставя пълен пример за други със същия въпрос. - person Giancarlo; 31.12.2013
comment
Flamerobin не знае как да замени value1 с някаква стойност, трябва да използвате някаква константа на стойност вместо име на променлива там, т.е. SELECT p.RESULT FROM TESTSP('foo') p. Що се отнася до цикъла, това е доста трудно с inpot, идващ от различни параметри за всяка стъпка, така че по-добре да развиете цикъла - напишете един и същ набор от оператори за всяка стъпка от цикъла, като използвате различни параметри. - person ain; 31.12.2013

Мисля, че вашата съхранена процедура трябва да изглежда така:

SET TERM ^ ; 
CREATE PROCEDURE TESTSP 
  ( A Varchar(64) ) 
  RETURNS ( result Integer ) 
AS 
BEGIN 
  IF (EXISTS (SELECT PRIMARYID 
              FROM TABLENAME 
              WHERE FIELD = 'Some string')) then 
     SELECT PRIMARYID 
       FROM TABLENAME 
       WHERE FIELD = 'Some string' 
       into :result;
  ELSE BEGIN
     result = gen_id(GEN_TABLEID, 1); 
     INSERT INTO TABLENAME 
       (PRIMARYID, FIELD) 
       VALUES (:result,  'Some string'); 
  END
END^ 
SET TERM ; ^
person guetlaur    schedule 31.12.2013

Ако имате множество инструкции за then и/или else клауза, трябва да използвате BEGIN ... END-блок!

SET TERM ^ ;

CREATE PROCEDURE TESTSP 
 ( A Varchar(64) ) 
RETURNS 
 ( RESULT Integer )
AS 

BEGIN
IF (EXISTS (SELECT PRIMARYID FROM TABLENAME WHERE FIELD = 'Some string')) then
  BEGIN
    SELECT PRIMARYID FROM TABLENAME WHERE FIELD = 'Some string' into :primaryid;
    result = PRIMARYID;
  END
ELSE 
  BEGIN
    INSERT INTO TABLENAME (FIELD) VALUES ('Some string');
    result = gen_id(GEN_TABLEID, 0);
  END
END^

SET TERM ; ^
person tico    schedule 30.12.2013
comment
Здравей Тико, благодаря ти за отговора, опитах това преди, но и то не се получи. Тогава получавам грешката, че колоната PRIMARYID е неизвестна - person Giancarlo; 31.12.2013