一个关于主从表的问题?(100分)

  • 主题发起人 主题发起人 zhengxq
  • 开始时间 开始时间
Z

zhengxq

Unregistered / Unconfirmed
GUEST, unregistred user!
由于主表和从表需要一个连接字段来连接,如一张帐单(主)
包含多种商品(从)需要一个ID字段来实现关联,以前一直
用DBase表,连接字段的值由程序控制(给出),现在发觉
这样太“低级”兼麻烦,而且用Paradox表有一种自动增量
的字段(Autoincrement),但由于该字段的值要到表实际
保存时才给出该值,因此在子表中(我用2个Table控件来实
现关联)不可能在保存前得到主表中连接字段(由表自动生成的)
的值,子表的连接字段总是不能自动获取该值,从而不能实
现关联,请问怎样解决这个问题(请详细点)?
另,大家是否看懂我写的内容?
 
先保存主表获得ID之后再保存副表喽。
如果考虑到数据库的可移植性建议你最好还是被用自动增加的字段。ID还是自己给的好。
larry
 
另,大家是否看懂我写的内容?
----你说的非常清楚.
这个问题跟那个MASTERID是怎么生成的一点关系都没有.

从表是无论如何也不能插入一条主表的主键中不存在的那个关联外键值的.

MASTER-DETAIL关联本来就是要MASTER的那个表里先有记录的.
(当然某种连接情况下,从表中可以存在一条记录,其关联键值主表中没有
对应记录的,但这个键值只能为NULL)

但是即使MASTER-DETAIL两个表里一条记录都没有,
这个MASTER-DETAIL关系也是可以轻松建立的
跟有没有数据没什么关系啊

总觉得你好象有点概念不清.
 
(当然某种连接情况下,从表中可以存在一条记录,其关联键值主表中没有
对应记录的,但这个键值只能为NULL)
----这里说的"从表中可以存在一条记录",不是真的一条,
真正意思是0/1/多.
 
一般应先录入主表的数据,之后再录入子表数据。
 
难道大家没有试过用两个Table控件来实现关联吗?
用TTable和TDBEdit,在与主表相连的TDBEdit中输入
主ID的值后,就不用在与从表相连的TDBEdit中输入
相关联的从ID值,在从表保存前,TTable会自动在
从表填入与主表相关联的ID值,就是在与主表相连
的TDBEdit中输入的那个ID值。

另外,大家在做这种主从表的时候,究竟是用程序
来控制(生成)ID值的情况多,还是利用数据库自己
生成ID的情况多,大家选择哪种,请把理由和各自的
优点告诉我。

还有,如果用程序来控制生成ID值,有什么好办法?
以前,我都要用到一个临时表(由主表复制来的),
来获得最后的一条记录的ID值(或最大ID值),从而确定新插入
的记录ID值(最后的一条记录的ID值+1),我一般
不让用户自己输入关联字段的ID值,因为主表的ID
是不能重复的,而且最好有规律,如:10000001-1000000X。
为什么要用临时表呢,我是因为:在表(主)插入记录时,
是不能使用查询的,因而不能获得最后一条记录的ID值,
而且有时最后一条记录的ID值,并不是最大的ID值,
因为考虑到删除的记录,因此必须一个临时表来进行
查询和判断,看看最大的ID值是多少,而且,在实际表
插入时的同时,还要将记录插入到临时表中,以确保
最大ID值没漏掉,这样就使记录插入的效率非常低,
大家看到我这种笨方法,肯定会很好笑,但我一直
就是这么干的,如有好办法,请大家多多赐教!!
 
难道大家没有试过用两个Table控件来实现关联吗?
----只有在桌面型简单应用中, 才可能用TTable控件.
因为它远不如直接操纵SQL来的自由.
还是再仔细看一下我第一个回答.

家在做这种主从表的时候,究竟是用程序
来控制(生成)ID值的情况多,还是利用数据库自己
生成ID的情况多,大家选择哪种,请把理由和各自的
优点告诉我。
----如果DBMS提供了自动生成序列的机制,
就用DBMS的.
如果没有,自己手工生成.

因为主表的ID是不能重复的,而且最好有规律,如:10000001-1000000X。
----为什么要有规律?

如果你是手工生成, 这种方式效率的确低下
我曾经这么做过:

建一个表,
字段只有ID, TableName
再看看下面代码, 体会一下.

function GetNextRecID(const ATableName: string): Integer;
var
strSql: string;
I: Integer;
ADOAAccessDB: TDOAAccessDB;
begin
Result := 0;
ADOAAccessDB := TDOAAccessDB.Create;
try
with ADOAAccessDB do
begin
strSql := 'SELECT * FROM PMIS.APP_RECID WHERE OBJ_RECID_TPNAME='''+ATableName+'''';
SqlOpenDOA(strSql);
if DataSet.State <> dsBrowse then
begin
DataSet.Close;
Exit;
end;
if DataSet.RecordCount<=0 then
begin
strSql := 'INSERT INTO PMIS.APP_RECID(OBJ_RECID_TPNAME, OBJ_RECID_RECID) VALUES(''' + ATableName + ''', 0)';
SqlExecDOA(strSql);
strSql := 'SELECT * FROM PMIS.APP_RECID WHERE OBJ_RECID_TPNAME = ''' + ATableName + '''';
SqlOpenDOA(strSql);
end;
if DataSet.RecordCount<=0 then
begin
DataSet.Close;
Exit;
end;
I := DataSet.FieldByName('OBJ_RECID_RECID').AsInteger;
I := I+1;
strSql := 'UPDATE PMIS.APP_RECID SET OBJ_RECID_RECID = '+IntToStr(I)+' WHERE OBJ_RECID_TPNAME = ''' + ATableName + '''';
SqlExecDOA(strSql);
strSql := 'SELECT * FROM PMIS.APP_RECID WHERE OBJ_RECID_TPNAME =''' + ATableName + '''';
SqlOpenDOA(strSql);
Result := DataSet.FieldByName('OBJ_RECID_RECID').AsInteger;
end;
finally
ADOAAccessDB.Free;
end;
end;







 
可以用TABLAE控件的POST函数试一试。
 
Paradox的单用户动态更新功能太强了,你可放两个table解决问题。
 
就我能看明白的说说
1。照你的情况 一般都不建议采用自增字段,改用手工编码也不失为一种办法
主从表的时候,还是结构稳定第一,或干脆找个其他字段值
2。如果一定要用,那可以判断“末记录ID数+1”的办法POST到从表,哦哪里出问题?
做临时表?效率。。。
3。
>难道大家没有试过用两个Table控件来实现关联吗?
个人认为QUERY比较灵活点
4。
>最好有规律,如:10000001-1000000X
可以控制自增字段的初始值来实现:如10000001(10000001-1000000X)
5.
>有时最后一条记录的ID值,并不是最大的ID值
自增字段不随删除而减小(自增是在主表吧?)
 
我从来不使用AutoInc型的字段,几乎也从来没用过TTable,
不过就你所说的内容,我相信很难实现,这一点,你自己说的已经比较明白了 :-)
因此,还是采纳上述诸位的建议,换一个模式的好。

ps:论坛的留言系统有email通知功能,因此有事情可以留言,
不要在别的贴子里写,那样给大家都造成很大麻烦,拜托把你的那个贴子也删除了,谢谢 :-)
 
多人接受答案了。
 
后退
顶部