Sql 带系统表的存储过程

Sql 带系统表的存储过程,sql,sql-server,stored-procedures,informix,Sql,Sql Server,Stored Procedures,Informix,我的数据库中有两个不同的系统表:Systables(存储数据库的所有表)和Syscolumns(存储数据库表的所有列) Systables包含:tabname和tabid Syscolumns包含:colname、tabid、colno 我必须编写以下程序: 我有两个新表-Tabela_sys(包含ns_Tabela和nome)和Campo_sys(ns_Campo,ns_Tabela,nome) 我想存储tabela_sys中不存在的systables数据,我想存储Campo_sys中不

我的数据库中有两个不同的系统表:
Systables
(存储数据库的所有表)和
Syscolumns
(存储数据库表的所有列)

  • Systables
    包含:tabname和tabid
  • Syscolumns
    包含:colname、tabid、colno
我必须编写以下程序:

  • 我有两个新表-Tabela_sys(包含ns_Tabela和nome)和Campo_sys(ns_Campo,ns_Tabela,nome)
  • 我想存储tabela_sys中不存在的systables数据,我想存储Campo_sys中不存在的syscolumns数据
  • 为此,我执行了以下步骤,并测试了一个案例,在该案例中,我在现有表中创建了一个新列
  • 预计在执行我的过程后,Tabela_sys将保持行数相等,Campo_sys将识别1个新行
这并没有发生,在执行该过程后,Campo_sys有更多的行

有人知道会出什么问题吗

CREATE PROCEDURE test ()

DEFINE cont       INTEGER;
DEFINE cont2       INTEGER;
DEFINE TabIdNum       INTEGER;
DEFINE varTabName,aa       VARCHAR (50,0);
DEFINE Nstabela       INTEGER;
DEFINE StrColName       VARCHAR (50,0);
DEFINE ColIdNum       INTEGER;

    FOREACH cur1 WITH HOLD FOR

        SELECT  tabid, tabname
        INTO    TabIdNum,varTabName
        from    systables
        WHERE   tabname not matches "sys*"

        --let aa=varTabName;

        SELECT  count(*), ns_tabela
        INTO cont, Nstabela
        FROM tabela_sys
        WHERE nome = varTabName
        GROUP BY 2;

        --let Nstabela=0;

        IF cont = 0 or cont is null THEN    
            INSERT INTO tabela_sys (ns_tabela, nome) 
            VALUES (0, varTabName);

            SELECT dbinfo('sqlca.sqlerrd1')
            INTO   Nstabela
            FROM   systables
            WHERE  tabname='systables';
        END IF;

    FOREACH cur2 WITH HOLD FOR

        SELECT  tabid, colname 
        INTO    ColIdNum, StrColName
        FROM    syscolumns 
        WHERE   tabid = TabIdNum        
        --AND   colname NOT IN (SELECT nome FROM campo_sys WHERE ns_tabela = Nstabela)  

        SELECT  count(*)
        INTO cont2
        FROM campo_sys
        WHERE nome = StrColName
        and   ns_tabela = Nstabela;

        --let Nscampo=0;

        IF cont2 = 0 or cont2 is null  THEN 
            INSERT INTO campo_sys (ns_tabela, nome) --(ns_campo, ns_tabela, nome) 
            VALUES (ColIdNum, StrColName); --(0, ColIdNum, StrColName);

        END IF;

    END FOREACH

    END FOREACH

END PROCEDURE;

当然,
tabela_sys
campo_sys
的行数会有所不同,因为第二个
foreach
是为
syscolumns
中的每一列运行的,并且每当为表找到一个新列时,就会插入
campo_sys

您的要求永远不会给出相同数量的记录,除非在使用现有过程时表的
syscolumns
为1(表示表中的一列,我认为这不是理想情况)


PS:我没有足够的声誉来评论,因此在这里添加一个答案。如果回答了您的问题,您可以接受作为答案;)

对这个过程有很多误解

首先,不要使用:

WHERE   tabname not matches "sys*"
如果有人创建一个表,比如说
system\u dest
,您将无法捕获它

排除系统表的最安全方法是:

WHERE   tabid > 99;
数据库中第一个用户定义表对象的tabid总是100。还有一些目录表不是以sys开头的,比如:
GL\u-COLLATE
GL\u-CTYPE
版本

您正在创建一个新的序列,而不是使用系统序列;你打算记录历史吗?如果有人删除一个表并使用相同的名称重新创建一个新表,那么这可能是错误的

只有在找不到记录时才进行更新,这意味着如果出现上述情况,则不会进行更新。如果有人删除或添加新列,它将不会反映在您的表中

您的第二个foreach有一个逻辑问题:

    SELECT  tabid, colname 
    INTO    ColIdNum, StrColName
    FROM    syscolumns 
    WHERE   tabid = TabIdNum        
在这个snipet中,您存储的是tabidcolname

    SELECT  count(*)
    INTO cont2
    FROM campo_sys
    WHERE nome = StrColName
    and   ns_tabela = Nstabela;
INSERT INTO campo_sys (ns_tabela, nome) --(ns_campo, ns_tabela, nome) 
VALUES (ColIdNum, StrColName); --(0, ColIdNum, StrColName);
然后根据系统的名称和给定的ID而不是tabid计算
campo_系统上的出现次数。因此,它将始终为0

    SELECT  count(*)
    INTO cont2
    FROM campo_sys
    WHERE nome = StrColName
    and   ns_tabela = Nstabela;
INSERT INTO campo_sys (ns_tabela, nome) --(ns_campo, ns_tabela, nome) 
VALUES (ColIdNum, StrColName); --(0, ColIdNum, StrColName);
最后,在
campo_sys
中插入存储系统的选项卡和colname

    SELECT  count(*)
    INTO cont2
    FROM campo_sys
    WHERE nome = StrColName
    and   ns_tabela = Nstabela;
INSERT INTO campo_sys (ns_tabela, nome) --(ns_campo, ns_tabela, nome) 
VALUES (ColIdNum, StrColName); --(0, ColIdNum, StrColName);
这就是为什么每次运行该过程时都会再次插入所有列

您是否考虑在目录表上使用<强>视图>强> >

CREATE VIEW tabela_sys (ns_tabela, nome) AS
    SELECT  tabid, tabname
    FROM    systables
    WHERE   tabid > 99;

CREATE VIEW campo_sys (ns_campo, ns_tabela, nome) AS
        SELECT  colno, tabid, colname
        FROM    syscolumns
        WHERE   tabid > 99;

如果需求需要一个物理表,最好的选择是使用。

您的问题被标记为SQL Server,但它看起来肯定不像SQ Server语法。也许是Informix语法?