如何 declare/use Firebird 客户端 DML 脚本中的局部变量

How to declare/use local variables in client-side DML scripts for Firebird

我是 Firebird DML 的新手。

在TransactSQL中我可以自由简单的声明和使用变量,如

declare @myID int

select @myID = 42

并在 SELECT 语句中使用这些变量

select * from mytable where id = @myID

并在不同语句之间传递值。

我的问题很简单,我如何在客户端 Firebird DML 脚本中声明和使用局部变量?

例如,使用 FlameRobin,我可以一次性执行一系列 DML 语句,例如

update mytable set price = 2 * price;
select * from mytable;

但我完全不知道如何声明和使用局部变量在它们之间传递值。

谷歌搜索,我遇到了 Firebird 的 PSql 的 EXECUTE BLOCK 构造,它显然支持 DECLARE VARIABLE,但它看起来很麻烦,似乎包含一些我在 TransactSQL 中从未遇到过的奇怪限制,似乎也没有旨在用于我正在尝试执行的那种客户端 DML 脚本。

拥有真实变量的唯一方法 - 正如您已经发现的那样 - 是使用 execute block(就所有意图和目的而言,它是一个匿名存储过程),或者 - 当然 - 一个普通的存储过程。

, you can also use a table to have variables, although I would suggest that you use a global temporary table 中所示,将变量 'private' 保存到连接或事务中。

还有一个选项(我之前完全忘记了)是使用 rdb$get_context and rdb$set_context 的上下文变量,尽管这可能会变得有点麻烦。例如设置变量 x 你可以使用:

select rdb$set_context('USER_SESSION', 'x', 5) from rdb$database;

如果变量是新创建的,则return值为0,如果变量已经存在,则值为1。值被转换为 VARCHAR(255),因此它们需要是可以转换为 VARCHAR(255) 的类型。您可以通过将变量设置为 NULL 来删除变量。除了 USER_SESSION,您还可以使用 USER_TRANSACTION.

The USER_SESSION context is bound to the current connection. Variables in USER_TRANSACTION only exist in the transaction in which they have been set. When the transaction ends, the context and all the variables defined in it are destroyed.

获取一个变量可以用

select rdb$get_context('USER_SESSION', 'x') from rdb$database;

如果变量不存在,returns NULL,否则 VARCHAR(255) 具有值。

过去几天我一直在努力解决这个问题,试图完成我对这个问题的回答:sql and fifo simple select;我花了大约半个小时来编写和测试 TransactSQL 方法来执行 OP 要求的操作。

我本来会按照向您建议的 EXECUTE BLOCK 路线进行操作,但我将 运行 保留在 DML 中,这些显然是不允许的,所以我放弃了这样做政治正确的方式。

因此,我采用的方式可能会让 Firebird 纯粹主义者大吃一惊:与其尝试声明变量,不如创建一个临时 table,其中包含与您将使用的变量对应的列,以及一个 ID一个使从中提取值变得容易,然后将变量的值存储在其中的一行中。类似于:

create table variables(ID int, myID int, myStringVar charchar(80), [etc...])

显然,您可以根据自己的喜好初始化此 table 并在进行时更新列值。访问其中的一个值比访问一个变量的值要麻烦一点,但也不多,如

update mytable set somecolumn = 666 where id = (select myID from variables where ID = 1)

我相信你明白了。 我发现以这种方式做事时唯一的小烦恼,而且我不确定它是 Firebird 还是 FlameRobin,似乎有必要包装像 tables 这样的 db 对象的创建并向上查看在您尝试使用它们的语句块之前提交的事务中。