【发布时间】:2021-01-14 01:02:55
【问题描述】:
我需要定义带有表类型输入参数的存储过程,例如,如果我从C#调用存储过程并将datatable作为参数传递给存储过程,会自动映射到列和字段?
我阅读了有关创建全局临时表的信息,但是如何在 Firebird 中用作输入参数?不知道有没有可能。
【问题讨论】:
我需要定义带有表类型输入参数的存储过程,例如,如果我从C#调用存储过程并将datatable作为参数传递给存储过程,会自动映射到列和字段?
我阅读了有关创建全局临时表的信息,但是如何在 Firebird 中用作输入参数?不知道有没有可能。
【问题讨论】:
Firebird 存储过程只接受标量值,因此您不能传递表类型的输入参数。解决方法是定义一个global temporary table (GTT) 作为存储过程的伴侣,并在调用存储过程之前填充该全局临时表。然后存储过程从全局临时表中读取。
需要明确的是,全局临时表是持久定义(您创建一次,然后它们可以被所有连接和用户重用(假设用户已被授予正确的权限)),而 GTT 中的数据是仅对当前事务(on commit delete rows;默认值)或当前连接(on commit preserve rows)可见。它们不像 SQL Server 中的(本地)临时表。
也就是说,这种临时表的定义是全局的和持久的,但数据是特定于事务或连接的。
所以,你要做的是定义一个全局临时表:
create global temporary table input_sp_example (
col1 integer,
col2 varchar(100)
) on commit delete rows
和一个示例存储过程
create procedure sp_example
returns (result1 integer, result2 varchar(8192))
as
declare col1_value integer;
declare col2_value varchar(100);
begin
for select col1, col2 from input_sp_example order by col1, col2 into col1_value, col2_value do
begin
if (col1_value is distinct from result1) then
begin
result1 = col1_value;
result2 = col2_value;
end
else
begin
result2 = result2 || col2_value;
end
suspend;
end
end
你可以这样称呼它:
insert into input_sp_example (col1, col2) values (1, 'a');
insert into input_sp_example (col1, col2) values (1, 'b');
insert into input_sp_example (col1, col2) values (1, 'c');
insert into input_sp_example (col1, col2) values (2, 'a');
select * from sp_example;
这个基本示例将产生一个结果
| RESULT1 | RESULT2 |
|---|---|
| 1 | a |
| 1 | ab |
| 1 | abc |
| 2 | a |
如果您在事务中执行一次存储过程,则无需执行任何其他操作(数据在提交时会自动删除)。如果您可能需要在单个事务中多次执行存储过程,则需要在使用新数据填充之前清空表:
delete from input_sp_example
【讨论】: