Определите переменную и запустите запрос с помощью EXECUTE BLOCK

у меня есть большой запрос в Firebird (который я запускаю с помощью FlameRobin), используя параметр повсюду, но получение запроса ниже для запуска будет делать:

SELECT * FROM customers WHERE customerid = 1234;

Я хочу, чтобы определить 1234 в качестве переменной, скажем customerID, чтобы я мог легко заменить его чем-то другим.

я узнал, что мне нужно положить это внутрь EXECUTE BLOCK.

EXECUTE BLOCK 
AS
DECLARE customerID INT = 1234;

BEGIN
  SELECT * FROM customers WHERE customerid = :customerID
END

если это имеет какое-либо значение, ошибка, которую я получаю, это Engine Message : Dynamic SQL Error SQL error code = -104 Unexpected end of command - line 3, column 26

2 ответов


проблема в том, что FlameRobin должен знать, когда заканчивается оператор и начинается следующий оператор. По умолчанию используется точка с запятой (;) для этого. ОднакоEXECUTE BLOCK по существу является хранимой процедурой, которая не хранится в базе данных, поэтому она содержит код PSQL, который также использует точку с запятой в качестве разделителя операторов.

следствием этого является то, что вы получаете синтаксические ошибки, потому что FlameRobin отправляет неполные операторы на сервер (то есть: он отправляет заявление после каждого ; это встречается).

вам нужно проинструктировать FlameRobin использовать другой Терминатор оператора, используя SET TERM. Другие инструменты запросов Firebird (например, isql) также требуют этого, но на самом деле это не часть синтаксиса самого Firebird!

поэтому вам нужно выполнить свой код как:

-- Instruct flamerobin to use # as the terminator
SET TERM #;
EXECUTE BLOCK 
AS
DECLARE customerID INT = 1234;

BEGIN
  SELECT * FROM customers WHERE customerid = :customerID;
END#
-- Restore terminator to ;
SET TERM ;#

однако это все равно приведет к ошибке, потому что этот запрос недействителен для PSQL: a SELECT в блоке PSQL требуется INTO предложение для сопоставления столбцов с переменными. И чтобы получить значения из EXECUTE BLOCK возвращенный к FlameRobin вам также нужно указать RETURNS предложение, как описано в документация EXECUTE BLOCK:

-- Instruct flamerobin to use # as the terminator
SET TERM #;
EXECUTE BLOCK 
   RETURNS (col1 INTEGER, col2 VARCHAR(100))
AS
DECLARE customerID INT = 1234;

BEGIN
  SELECT col1, col2 FROM customers WHERE customerid = :customerID INTO :col1, :col2;
  SUSPEND;
END#
-- Restore terminator to ;
SET TERM ;#

насколько я знаю SUSPEND технически здесь не требуется, но Flamerobin не будет извлекать возвращенную строку, если она не включена.

однако вышеизложенное не будет работать, если select создает несколько строк. Для этого вам нужно использовать FOR SELECT ... DO в сочетании с SUSPEND:

-- Instruct flamerobin to use # as the terminator
SET TERM #;
EXECUTE BLOCK 
   RETURNS (col1 INTEGER, col2 VARCHAR(100))
AS
DECLARE customerID INT = 1234;

BEGIN
  FOR SELECT col1, col2 FROM customers WHERE customerid = :customerID INTO :col1, :col2
  DO
     SUSPEND;
END#
-- Restore terminator to ;
SET TERM ;#

на SUSPEND здесь возвращает строку и ждет, пока абонент получит эту строку, а затем продолжает с FOR петли. Таким образом, он будет повторять результаты.

IMHO это слишком много усилий для параметризации. Возможно, вы захотите просто не параметризовать при использовании flamerobin или использовать инструмент, поддерживающий запрос значений параметров для обычных заполнителей параметров Firebird (но быть честно говоря, я не уверен,что они есть).


SET TERM #;
EXECUTE BLOCK
RETURNS (COL1  Varchar(5) , COL2 INTEGER , COL3 INTEGER )
AS
DECLARE customerID  INT = 5;
BEGIN
  FOR SELECT COSP.OSP_COMPON,COSP.OSP_DIAS FROM COSP WHERE COSP.OSP_ORDEM=2 INTO COL1 , COL3
  DO
  FOR SELECT CMES.MESNUM FROM CMES WHERE CMES.MESNUM = customerID  INTO COL2 DO SUSPEND;
  SUSPEND;
END#
SET TERM ;#

почему к осени ?