2013-03-19 2 views
3

J'utilise IDS 11.70. Je veux être en mesure d'obtenir le nombre de colonnes dans une table temporaire, donc dans le code 4gl/genero, je peux avoir une fonction qui place le bon nombre de points d'interrogation dans une instruction 'mettre un curseur'.Informix: compte le nombre de colonnes dans une table temporaire?

Par exemple, veulent remplacer ce genre de code:

declare put_curs1 cursor for 
    insert into my_temp_table values(?,?,?,?,?,?) 

Avec quelque chose comme ceci:

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 

Nous le faisons déjà pour nos tables régulières, donc si le schéma de la table doit être changé pour avoir plus ou moins de colonnes alors le code ne rompra pas avec le mauvais nombre de colonnes sur les insertions en utilisant les curseurs put. Dans cette fonction pour les tables régulières, pour obtenir le nombre de colonnes que nous utilisons:

select count(*) 
    from systables, syscolumns 
    where systables.tabname = table_name 
    and systables.tabid = syscolumns.tabid 

Mais en essayant de le faire pour les tables temporaires, je ne vois pas ce que je me joins ou quelle colonne indique le nombre de colonnes sont dans la table temporaire. Voilà ce que j'ai jusqu'à présent:

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; 

Ainsi, au lieu de select * j'ai besoin select count(columns) - mais où dois-je me joins à donc je peux compter les colonnes? J'ai fouillé autour mais ne peux pas trouver la jointure dont j'ai besoin.

Merci, Bryce Stenberg

Répondre

1

La manière classique de le faire est de préparer « SELECT * FROM temptable », décrivez la déclaration, et obtenir le nombre de colonnes de la description, puis libérer la déclaration préparée. Cela implique de descendre dans ESQL/C, bien que ... ou le fait probablement.

code non testé - avec veule à un contrôle d'erreur inexistante:

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); 
} 

Appel à I4GL:

DEFINE n INTEGER 

LET n = cols_in_temp_table("the_temp_table") 

Le code sera effectivement travailler pour une table, temporaire ou non, de sorte que la fonction le nom est un léger abus.

Je ne trouve rien dans la base de données sysmaster qui vous indique les colonnes d'une table temporaire. Ce n'est pas tout à fait la même chose que «il n'y a pas de telle table», mais c'est assez proche.

+0

Bonjour Jonathan, dans notre environnement, nous n'utilisons aucun ESQL/C donc je ne serai pas en mesure de mettre en œuvre votre solution. Nous utilisons seulement Genero pour notre codage. La base de données doit savoir quelles colonnes sont dans les tables temporaires quelque part, peut-être quelqu'un sait où le trouver ... Merci pour votre réponse. Cordialement, Bryce Stenberg. – user1840734

1

J'ai testé le code ci-dessous avec succès sur ifx 11.50 FC9.

WARNING: J'ai utilisé une fonction non documentée. Je ne sais pas si l'utiliser en toute sécurité sur la production ...

Comment ça marche: je "transforme" la ligne en type de données ROW; utilisez une fonction interne appelée collectionoutput pour convertir cette ROW en lvarchar, puis comptez combien de virgules ont (séparateur de colonnes).

Pré-requis: autorisation de créer/exécuter la fonction; la table temporaire doit avoir au moins 1 ligne.

--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; 

mes sorties (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 
+0

Salut, désolé, il a fallu si longtemps pour répondre. – user1840734

+0

Salut, désolé, il a fallu si longtemps pour répondre. J'ai essayé votre code ci-dessus et cela fonctionne. Toutefois, lorsque j'essaie de l'utiliser avec l'une de nos tables temporaires réelles créées avec 'select * from myTable dans temp TmpMyTable sans log', j'obtiens des erreurs de' Code d'erreur: -9930, Byte, Text, Serial, Serial8 ou Bigserial types de données dans les types de collections non autorisés. »Nous utilisons des publications en série dans beaucoup de tableaux, ce qui semblait prometteur, mais pas adapté à ma situation. Je suppose que la fonction non documentée est le 'collectionoutput'? Je peux apporter cette question à la liste de l'IIUG pour plus d'idées. Merci, Bryce. – user1840734

0

Pour votre information - Si vous utilisez 12.10 - Peut créer une instance réelle de votre table temporaire et obtenir des colonnes comptent à partir des tables système.

1) CREATE TABLE votretemp_chck SELECT * FROM votretemp où 1 = 2; 2) Vérifier tables sys pour le nombre de colonnes 3) Laissez tomber yourtemp_chck

Bien que je ne l'ai pas essayé de créer une vraie table à partir d'une température un mais ne fonctionne avec de vrai réel pour v12.10.

Dans n'importe quelle version pourrait également juste créer la vraie table ainsi peut obtenir le compte de colonne des tables de système et laisser tomber après. J'ai vu ça en très vieux 4GL. Pas quelque chose d'id faire à moins d'aucune autre option.

+0

Merci pour cette idée - j'essaierai quand j'aurai le temps, bien que je cours actuellement 11.70. Je vais commenter ici une fois que j'ai essayé. À la vôtre, Bryce. – user1840734

Questions connexes