如何在Firebird的客户端DML脚本中声明/使用本地变量



我是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脚本。

在过去的几天里,我一直在努力解决这个问题,试图完成对这个q:sql和fifo简单选择的回答;我花了大约半个小时来编写和测试一种TransactSQL方法来完成OP的要求。

我本可以走向你建议的EXECUTE BLOCK路线,但我一直遇到DML中显然不允许的事情,所以我放弃了以政治正确的方式做这件事。

因此,我这样做的方式可能会让Firebird纯粹主义者大吃一惊:与其试图声明变量,不如创建一个临时表,其中包含与您将要使用的变量相对应的列,以及一个ID表,以便轻松地从中提取值,然后将变量的值存储在其中的一行中

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

显然,您可以随心所欲地初始化此表,并在执行过程中更新列值。访问其中的值比访问变量的值要麻烦一些,但不像那样麻烦很多

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

我相信你已经明白了。我发现用这种方式做事唯一的小问题是,在尝试使用一组语句之前,似乎有必要将创建数据库对象(如表和视图)打包到一个提交的事务中。

正如您已经发现的那样,拥有真实变量的唯一方法是使用execute block(无论出于何种目的,它都是一个匿名存储过程),或者——当然——一个普通存储过程。

正如MartynA的回答所示,您也可以使用表来包含变量,尽管我建议您使用全局临时表,因为这会使变量对连接或事务保持"私有"。

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

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

如果变量是新创建的,则返回值为0;如果变量已经存在,则返回1。值被转换为VARCHAR(255),因此它们需要是可以强制转换为VARCHAR(255)的类型。您可以通过将变量设置为NULL来删除该变量。您也可以使用USER_TRANSACTION来代替USER_SESSION

USER_SESSION上下文绑定到当前连接。USER_TRANSACTION中的变量仅存在于已设置变量的事务中。当事务结束时,上下文和其中定义的所有变量都将被销毁。

可以使用获取变量

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

如果变量不存在,则返回NULL,否则返回值为的VARCHAR(255)

最新更新