定义变量并使用EXECUTE BLOCK运行查询

时间:2013-10-10 14:00:36

标签: firebird interbase firebird2.5

我在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 个答案:

答案 0 :(得分:14)

问题是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无效:PSQL块中的SELECT需要INTO子句将列映射到变量。要从EXECUTE BLOCK返回FlameRobin中获取值,您还需要指定documentation of EXECUTE BLOCK中所述的RETURNS子句:

-- 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 ... DOSUSPEND结合使用:

-- 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循环。这样它就会迭代结果。

恕我直言,这种参数化的努力太多了。您可能想要考虑在使用flamerobin时不进行参数化,或者使用支持为Firebird的常规参数占位符请求参数值的工具(但说实话我不确定是否有)。

答案 1 :(得分:-2)

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 ;#

为什么会跌倒?