我的数据库中有两个不同的系统表:Systables
(存储数据库的所有表)和Syscolumns
(存储数据库表的所有列)。
Systables
包含:tabname和tabid; Syscolumns
包含:colname,tabid,colno。我必须编写以下程序:
在执行此过程后,它没有发生,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;
答案 0 :(得分:0)
当然,tabela_sys
和campo_sys
的行数会有所不同,因为foreach
中的每个列都会运行第二个syscolumns
,并且每当找到新列时对于表格,插入了campo_sys
。
在使用现有程序时,除非表的syscolumns
为1(表示我认为不理想的情况下表中的一列),否则您的要求永远不会给出相同数量的记录。
PS:我没有足够的声誉发表评论,因此在此处添加了答案。如果它回答了你的问题,你可以接受答案;)
答案 1 :(得分:0)
对手术有很多误解。
首先,不要使用:
WHERE tabname not matches "sys*"
如果有人创建了一张桌子,让我们说system_dest
,你就不会抓住它。
排除系统表的最安全方法是:
WHERE tabid > 99;
数据库中第一个用户定义的表对象的 tabid 始终为 100 。并且目录表不以 sys 开头,例如:
GL_COLLATE
,GL_CTYPE
和VERSION
。
您正在创建新的序列而不是使用系统序列;你打算保留历史吗?如果有人丢弃一个表并使用相同的名称重新创建一个新表,这可能是错误的。
如果没有找到记录,您只会更新,这意味着如果上述情况发生,您将无法更新。如果有人丢弃或添加新列,它将不会反映在您的表格上。
您的第二个 foreach 有一个逻辑问题:
SELECT tabid, colname
INTO ColIdNum, StrColName
FROM syscolumns
WHERE tabid = TabIdNum
在此snipet中,您将存储 tabid 和 colname 。
然后,您可以使用名称和您指定的 ID 而不是系统的 tabid 来计算campo_sys
上的匹配项。因此它总是 0 。
SELECT count(*)
INTO cont2
FROM campo_sys
WHERE nome = StrColName
and ns_tabela = Nstabela;
最后,您插入campo_sys
存储系统的 tabid 和 colname 。
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;
如果需要物理表,最佳选择是使用Merge Statement。