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
(存储数据库表的所有列)
包含:tabname和tabid李>Systables
包含:colname、tabid、colnoSyscolumns
- 我有两个新表-Tabela_sys(包含ns_Tabela和nome)和Campo_sys(ns_Campo,ns_Tabela,nome)
- 我想存储tabela_sys中不存在的systables数据,我想存储Campo_sys中不存在的syscolumns数据
- 为此,我执行了以下步骤,并测试了一个案例,在该案例中,我在现有表中创建了一个新列李>
- 预计在执行我的过程后,Tabela_sys将保持行数相等,Campo_sys将识别1个新行李>
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中,您存储的是tabid和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);
然后根据系统的名称和给定的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语法?