我正在使用IDS 11.70。
我希望能够获得临时表中列数的计数,所以在4gl / genero代码中我可以使用一个函数将正确数量的问号放入'put cursor'语句。
例如,想要替换这种代码:
declare put_curs1 cursor for
insert into my_temp_table values(?,?,?,?,?,?)
有这样的事情:
let str = "insert into my_temp_table values (
format_place_holder_string_for_insert( "my_temp_table" ) CLIPPED, ")"
prepare put_stment1 from str
declare put_curs1 cursor for put_stment1
我们已经为常规表执行此操作,因此如果应将表架构更改为具有更多或更少的列,则使用put游标在插入时代码不会因错误的列数而中断。 在常规表的此函数中,为了获得我们使用的列数:
select count(*)
from systables, syscolumns
where systables.tabname = table_name
and systables.tabid = syscolumns.tabid
但是在尝试为临时表执行此操作时,我无法看到我加入的内容或哪个列指示临时表中有多少列。这就是我到目前为止所做的:
select *
FROM sysmaster:systabnames n, sysmaster:systabinfo i, sysmaster:syssessions s
WHERE sysmaster:bitval(i.ti_flags, "0x0020") = 1
AND n.dbsname = database_name
AND i.ti_partnum = n.partnum
AND s.sid = dbinfo("sessionid")
AND n.tabname = table_name;
所以我需要select *
而不是select count( columns )
- 但我在哪里加入,以便我可以计算列数?我四处寻找但找不到我需要的连接。
谢谢, 布莱斯斯滕贝格
答案 0 :(得分:1)
这样做的经典方法是准备'SELECT * FROM temptable',描述语句,并从描述中获取列数,然后释放准备好的语句。这涉及到降低到ESQL / C,但是......或者很可能会这样做。
未经测试的代码 - 有松弛到不存在的错误检查:
int cols_in_temp_table(int nargs)
{
$ char buffer[300];
struct sqlda *u;
char tabname[129];
if (nargs != 1)
ibm_lib4gl_fatalError(...);
popstring(tabname, sizeof(tabname));
sprintf(buffer, "SELECT * FROM %s", tabname);
$ PREPARE p FROM :buffer;
$ DESCRIBE p INTO u;
retint(u.sqld);
$ FREE p;
free(u);
return(1);
}
拨打I4GL:
DEFINE n INTEGER
LET n = cols_in_temp_table("the_temp_table")
代码实际上适用于任何表,临时或非临时,因此函数名称有点用词不当。
我在sysmaster
数据库中找不到任何告诉您临时表中列的内容。这与“没有这样的表”并不完全相同,但它非常接近它。
答案 1 :(得分:1)
我在ifx 11.50 FC9上成功测试了代码。
WARNING:
我使用了一个未记录的函数。我不知道是否可以安全地使用它而不是生产......
如何运作:我"转换"行到ROW数据类型;使用一个名为collectionoutput的内部函数将此ROW转换为lvarchar,然后计算逗号的数量(列分隔符)。
Pre-req:创建/运行该功能的权限;临时表至少必须有1行。
--drop function count_cols;
create function count_cols ( cols lvarchar(4000) ) returning int ;
define i int;
define ncols int;
define isstring int;
let ncols = 1;
let isstring = 0;
for i = 1 to length(cols)
if substr(cols,i,1) = "'" and isstring = 1 then
let isstring = 0 ;
continue for;
end if ;
if substr(cols,i,1) = "'" and isstring = 0 then
let isstring = 1 ;
continue for;
end if ;
if isstring = 0 and substr(cols,i,1) = ',' then
let ncols = ncols+1 ;
end if ;
end for ;
return ncols;
end function
;
--drop table t2;
create temp table t2 ( cod int, desc char(100) default 'test', data datetime year to second default current year to second , number int);
insert into t2 (cod)values (0);
insert into t2 (cod)values (0);
insert into t2 values (1,'teste,teste,teste,teste',current, 0);
select * from t2;
select collectionoutput(multiset(select first 1 * from t2 where cod = 1)) from sysmaster:sysdual ;
select count_cols(collectionoutput(multiset(select first 1 * from t2 where cod = 1))) from sysmaster:sysdual;
我的输出(dbaccess)
cod 0
desc test
data 2013-03-22 11:36:37
number
cod 0
desc test
data 2013-03-22 11:36:37
number
cod 1
desc teste,teste,teste,teste
data 2013-03-22 11:36:37
number 0
(expression) MULTISET{ROW(1 ,'teste,teste,teste,teste
','2
013-03-22 11:36:37',0 )}
(expression)
4
答案 2 :(得分:0)
仅供参考 - 如果使用12.10 - 可以创建临时表的真实实例并从系统表中获取列数。
1)CREATE TABLE yourtemp_chck SELECT * FROM yourtemp,其中1 = 2; 2)检查sys表中的列数 3)删除yourtemp_chck
虽然我没有尝试从临时表创建一个真正的表,但是对于v12.10确实可以使用真实的表。
在任何版本中也可以只创建真实的表,这样可以从系统表中获取列数并在之后删除。我在很老的4GL中看过这个。除非没有其他选择,否则不能做id。