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

Val*_*spa 6 firebird interbase firebird2.5

我在Firebird中有一个大型查询(我使用FlameRobin运行),在整个地方使用参数,但是让下面的查询运行将会:

SELECT * FROM customers WHERE customerid = 1234;
Run Code Online (Sandbox Code Playgroud)

我想把它定义1234为一个变量,比如说customerID我可以用其他东西轻松替换它.

我已经知道我需要把它放进去EXECUTE BLOCK.

EXECUTE BLOCK 
AS
DECLARE customerID INT = 1234;

BEGIN
  SELECT * FROM customers WHERE customerid = :customerID
END
Run Code Online (Sandbox Code Playgroud)

如果有任何重要性,我得到的错误是 Engine Message : Dynamic SQL Error SQL error code = -104 Unexpected end of command - line 3, column 26

Mar*_*eel 14

问题是FlameRobin需要知道语句何时结束并且下一个语句开始.默认情况下,它使用分号(;).但是,EXECUTE BLOCKa本质上是一个未存储在数据库中的存储过程,因此它包含也使用分号作为语句分隔符的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 ;#
Run Code Online (Sandbox Code Playgroud)

但是,执行此操作仍会导致错误,因为此查询对PSQL无效:SELECTPSQL块中的A 需要一个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 ;#
Run Code Online (Sandbox Code Playgroud)

据我所知,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 ;#
Run Code Online (Sandbox Code Playgroud)

SUSPEND这里返回该行并等待来电者已经获取该行,然后用不断FOR循环.这样它将迭代结果.

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