在李维的<<Delphi5.x ADO/MTS/COM+>>一书中,提到了“处理多个数据表Join的数据”,根据书中的介绍,我做了如下的测试:数据库:oracle9i表A:客户信息表
字段:CustNo,CustName,CustTypeNo表B:客户类别表
字段:CustTypeNo,CustTypeName表A和表B通过CustTypeNo关联。现在做一个对表A:客户信息表的添加操作,其中TADOQuery设为了BatchUpdate模式,对于数据的输入都采用DbEdit控件:1.首先打开表A: with ADOQuery do
 begin 
   close
   sql.text := 'SELECT A.CustNo,A.CustName,A.CustTypeNo,B.CustTypeName '+
               'FROM A  LEFT JOIN B ON A.CustTypeNo=B.CustTypeNo '+
               'ORDER BY A.CustNo ';
   open;
 end;2.添加一条记录  ADOQuery.append;
  ADOQuery.fieldbyname('CustNo').asstring := '1001';
  ADOQuery.fieldbyname('CustTypeName').asstring := '测试客户';
  ADOQuery.fieldbyname('CustTypeNo').asstring := '01';
  ADOQuery.fieldbyname('CustTypeName').asstring := '海外客户'; 3.保存记录  ADOQuery.UpdateBatch;   出现的问题如下:保存记录是提示错误“Ora-00904:CustTypeName无效的标示符”,我想,ADOQuery.UpdateBatch方法执行后,最后自动生成的SQL语句,可能把CustTypeName字段作为了表A:客户信息表的字段了。可是从李维的书里了解到,ADO比BDE先进的一个地方就是在多表联接时的数据更新,能够自动为每个表生成相应的SQL语句。
   其实,对于ADOQuery.fieldbyname('CustTypeName').asstring := '海外客户'这一句的作用,主要是为了在DBGrid中适时的显示CustTypeNo所对应的CustTypeName值,相信大家也经常这样用。
   注:不想采用TDBNavigator控件   恳请有经验的兄弟帮忙看看。

解决方案 »

  1.   

    Oracle SQL文:SELECT A.CustNo, A.CustName, A.CustTypeNo, B.CustTypeName 
    FROM A, B
    WHERE A.CustTypeNo=B.CustTypeNo(+) 
    ORDER BY A.CustNo意思是:如果在B表中没有找到B.CustTypeNo、B.CustTypeName字段自動补空
      

  2.   

    现在的问题不是oracle的Sql语句的问题,我用Left Join方式进行左外连接,与(+)方式的作用是一样的。
      

  3.   

    我昨天也出现过这种问题
    结果我把 ADOQuery换了一个新的,名字用原来的就可以,我也觉得很怪!~
    我觉得你这种操作,最好在SQL server的查询分析器中建一个视图来操作
      

  4.   

    oracle的Sql语句中有Left Join方式进行左外连接吗?把你的Sql语句在Oracle SQL Plus等工具中执行一下,看对吗?
      

  5.   

    oracle 8i里还没有Left Join,但是9i里已经加进去了!!
    感谢各位的答复,我的代码都是经过调试的,我可以向大家保证。大家的回复大多都把注意力放在了Sql语句上了,而我的主要问题还是关于Delphi中ADO处理多表联结时,更新主表的问题。
      

  6.   

    ADOQuery.append;
    ADOQuery.fieldbyname('CustNo').asstring := '1001';
    ADOQuery.fieldbyname('CustTypeName').asstring := '测试客户'; 
    //――――按NI自己的SQL文、↑此処的字段名応該是CustName吧?
    {...}
      

  7.   

    TO: cronuz(cronus) 
    我一时疏忽写错了,应该是:
    ADOQuery.fieldbyname('CustName').asstring := '测试客户'; 不过这不是造成最终不能添加记录的的原因!!!
    其实,如果大家有空,可以自己找个多表联结,写代码试试,我相信只要在机子上亲自调试一下,很多问题都会凸现出来。
      

  8.   

    hehe~~~、其実我己経有所認識、不過我用的是Oracle8i、Left Join方式的存在確実不知。一)在B表中有:CustTypeNo、CustTypeName
     当ADOQuery.append時、只対B表中的CustTypeName追加記録、
     1.若CustTypeNo文段是B表中的PrimaryKey、会出錯。
     2.按你的録入方法在B表中的CustTypeNo文段一定NULL,
       那你上述的SQL文B.CustTypeName也会是NULL。二)還有你可以建一個View、在Oracle環境下、検証你的SQL文是否可行。CREATE VIEW yourView_Name AS 
    SELECT A.CustNo,A.CustName,A.CustTypeNo,B.CustTypeName
      FROM A  LEFT JOIN B ON A.CustTypeNo=B.CustTypeNo
    ORDER BY A.CustNoINSERT INTO yourView_Name 
    VALUES ('1001', '测试客户', '01', '海外客户');
      

  9.   

    TO:cronuz(cronus) 首先非常感谢你的热心回复! 关于这个问题,有一点我需要说明一下,我的初衷是只对表A:客户信息表进行相应的添加,修改,删除操作。打开表时,为什么我要去关联CustTypeName表,目的是把表B:客户类别表中的CustTypeName一起显示给客户,总不能只显示CustTypeNo吧。我并不想在维护表A的同时,去影响表B的数据,可是ADO在多表联结查询后的数据更新方面,似乎是关联几个表,它就同时产生几个相应的SQL语句去更新相应的表,如果是这样,那么ADO这方面的技术没有意义。
      

  10.   

    目的是只对表A修正、那就把显示TDataSet和実際更改TDataSet分成二個...
    実際解決問題、有時是不看技术上有没有意义的、hehe~~~
      

  11.   

    cronuz,我看了很多这方面的贴子,都没有完全很好的解决的ADO多表联结后,只对主表更新的问题。所以,我想参考BDE中的TUpdateSql的思想,自己写一个适用于ADO的TADOUpdateSql控件,这样一来,就可以从根本上解决这个问题。
      

  12.   

    "主表更新的问题"、在你的SQL文中、好象不分主表和从表吧?
    B表并不是A表的从表呀、A表是做修改,删除、并不影響B表!
    厳格的説:B表是MASTER、A表是INFORMATION。
    建議你看看主从表方面的書...
      

  13.   

    cronuz(cronus):
    你不会以为我连“主从表”的概念的都不懂吧^-^,我之所以用“主表更新”这个词语,主要还是想说明白我只想更新多表连接中某一单表。不过这个问题我已经解决了,自己写一个适用于ADO的TADOUpdateSql控件,适用于任何多表查询,单表更新问题。再次感谢你的热心参与回复。
      

  14.   

    hehe~~~、楼主”自己写一个适用于ADO的TADOUpdateSql控件,适用于任何多表查询,单表更新问题”、强! 
    什麽时侯公开呀? 很想拜读!