0

Using Delphi 7/AdoQuery

qry1.close;
qry1.sql.clear;
qry1.SQL.text:=**'UPDATE ardata SET saletodate = (SELECT sum(tot_rm_amt) from saledat where saledat.short_name=ardata.short_name )';**

//qry1.SQL.text:='UPDATE ardata SET saletodate =0' ; This works
qry1.execsql;

Nb. ardata=ardata.dbf/saledat=saledat.dbf,saletodate=ardata->saletodate,tot_rm_amt= saledat->tot_rm_amt

error : Microsoft ODBC Visual Foxpro Driver Function Name is Missing when using Delphi 7 ADO Query

What is causing the error msg ?

jarlh
  • 42,561
  • 8
  • 45
  • 63
CCH4BI
  • 1
  • 1
  • You are not really giving details and you are saying both ADO and ODBC??? With ADO you mean it is OLEDB, no? VFPOledb is an OleDb driver and has nothing to do with ODBC. " Microsoft ODBC Visual Foxpro Driver" - There is no Microsoft ODBC driver for VFP after version 6. – Cetin Basoz Mar 27 '23 at 14:02

1 Answers1

1

Your error should be that you messed up OLEDB and ODBC drivers. Use VFPOLEDB (OLEDB) driver and all should be OK. For example this works perfectly fine in C# (sample arData and saleDat are in d:\backyard\temp):

void Main()
{
    using (OleDbConnection cn = new OleDbConnection(@"Provider=VFPOLEDB;Data Source=d:\backyard\temp"))
    {
        string sql = @"UPDATE ardata 
            SET saletodate = (SELECT sum(tot_rm_amt) 
               from saledat 
               where saledat.short_name=ardata.short_name )";
        cn.Open();     
        var rowsAffected = new OleDbCommand(sql, cn).ExecuteNonQuery();
        cn.Close();
        
        Console.WriteLine(rowsAffected);
    }
}

EDIT: When there are no matching short_name in saleDat this would fail if saleToDate doesn't accept nulls. You can fix it in two ways:

Applying VFP specific nvl() to sum():

string sql = @"UPDATE ardata 
            SET saletodate = (SELECT nvl(sum(tot_rm_amt), 0)
               from saledat 
               where saledat.short_name=ardata.short_name )";

Rewriting the SQL in a more ANSI compatible manner:

string sql = @"UPDATE ardata 
            SET saletodate = tmp.totAmt 
               from (select short_name, sum(tot_rm_amt) as totAmt
                     from saleDat
                     group by short_name) tmp
               where tmp.short_name=ardata.short_name";

What the latter one does is: It gets all the sums for all the short_names available in saleDat into a tmp cursor (looks like):

short_name, totAmt
1, 10
2, 15

Then uses that tmp cursor as the source matching tmp.short_name = ardata.short_name.

Unlike the former, for the non-matching ones no update is applied (instead of setting to 0, they are left as is).

Cetin Basoz
  • 22,495
  • 3
  • 31
  • 39
  • U are right, should have used the VPFoledb. Now get saletodate does not accept null values. How to adjust the sql statement to block out null values in SET saletodate = (SELECT sum(tot_rm_amt) from saledat where saledat.short_name=ardata.short_name )" – CCH4BI Mar 29 '23 at 02:45
  • SET saletodate = (SELECT sum(tot_rm_amt) from saledat where (saledat.short_name=ardata.short_name ) and saledat.tot_rm_amt is not null" does not work... still getting saletodate not accepting null values – CCH4BI Mar 29 '23 at 03:26
  • If there is no corresponding short_name in saledat then the sum would be null. You could correct it in two ways: 1) Wrapping sum() with VFP specific nvl() function, 2) Rewriting the SQL in an ANSI SQL compatible (better approach IMHO). I will edit sample for both of them. – Cetin Basoz Mar 29 '23 at 11:06