home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / database / db4bugs.zip / ANOMALY2.TXT < prev    next >
Text File  |  1988-12-23  |  6KB  |  159 lines

  1.  
  2. In keeping with our commitment to provide you, the user, with support
  3. that will maximize your productivity with the dBASE IV product, we are
  4. continuing our tradition of publishing timely, detailed anomaly and 
  5. work-around reports.
  6.  
  7. The following listing addresses three known anomalies when using
  8. dBASE IV SQL commands. Use of these techniques will aid you in
  9. avoiding anomalies that have been reported to our Software Support
  10. Center.  This report will be supplemented as new information is
  11. received.
  12.  
  13. *******************************************************************
  14.  
  15. The following queries either fail with an "Internal Error" when
  16. executed by dBASE IV's SQL, or give incomplete results.  Three
  17. distinct anomalies are responsible for the seven failing queries:
  18.  
  19.  
  20. a)   If the data in a table is more than 95% physically sorted on a
  21.      field,
  22.           BUT less than 100% sorted,
  23.           AND that field is indexed
  24.  
  25.      the SQL optimizer will assume that the field is, in fact,
  26.      100% sorted.  SQL queries against that field will miss the
  27.      records which are out of order.  
  28.  
  29. The most likely ways for a user to get a data file "almost in order"
  30.      are:
  31.      
  32.      - the user begins using an application for the first time,
  33.      and enters a large quantity of data in sorted order (such as
  34.      typing in an address book).  The user then starts adding,
  35.      deleting, and changing records.  While the number of changed
  36.      records is less than 5% of the database, the anomaly can
  37.      occur if the critical field is also indexed.
  38.      
  39.      - the user has an application which uses the dBASE SORT
  40.      command to generate a physically sorted file for reporting
  41.      purposes.  The application also updates the file.  The user then
  42.      adds an SQL "addition" to the existing dBASE application.
  43.      
  44. EXAMPLES:
  45.  
  46.     1. SELECT DISTINCT CLIENTS.ACCTNUM, NAME FROM CLIENTS,
  47.         TRANSACT
  48.            WHERE CLIENTS.ACCTNUM = TRANSACT.ACCTNUM
  49.               AND SYMBOL IN 
  50.                   (SELECT SYMBOL FROM TRANSACT
  51.                     WHERE ACCTNUM=1002);
  52.  
  53.     2. SELECT DISTINCT CLIENTS.ACCTNUM, NAME FROM CLIENTS,
  54.         TRANSACT
  55.            WHERE CLIENTS.ACCTNUM = TRANSACT.ACCTNUM
  56.               AND SYMBOL IN 
  57.                   (SELECT SYMBOL FROM TRANSACT
  58.                     WHERE ACCTNUM=1002)
  59.                   AND ACCTNUM = 1144;
  60.  
  61.      Note 1: This query returns an "Ambiguous column name" error since
  62.      the column "ACCTNUM" is in both tables.  The last line in example
  63.      2 should read "AND CLIENTS.ACCTNUM = 1144".
  64.      
  65.  
  66.          3. SELECT distinct NAME FROM CLIENTS
  67.                WHERE "GM" IN
  68.             (SELECT trim(SYMBOL) FROM TRANSACT
  69.                 WHERE ACCTNUM = CLIENTS.ACCTNUM);
  70.  
  71.      Note 2: One needs to add the "DISTINCT" keyword and the
  72.      "TRIM()" function indicated above in lower case to get the
  73.      right results.  
  74.  
  75.           4. SELECT ACCTNUM, COUNT(*) FROM TRANSACT
  76.                GROUP BY ACCTNUM
  77.                 HAVING COUNT(*) > 60;
  78.  
  79.      WORK-AROUND:
  80.      
  81.      Observe that all four queries involve selections involving the
  82.      column TRANSACT.ACCTNUM which is also indexed.  This is the field
  83.      which is "almost in order".  The work-around is to drop the index
  84.      on the field.
  85.      
  86.  
  87. b)   If a query contains an existential predicate ("WHERE EXISTS..."),
  88.          AND contains a nested subquery,
  89.              WHICH has a local predicate,
  90.              AND WHICH is against a table of more than 5,000 records,
  91.  
  92.      then the user MAY get an "Internal Error".  The error is
  93.      handled normally by dBASE IV's error trapping.  
  94.  
  95. EXAMPLES:
  96.  
  97.      1. SELECT NAME FROM CLIENTS
  98.         WHERE NOT EXISTS
  99.           (SELECT * FROM TRANSACT
  100.              WHERE ACCTNUM = CLIENTS.ACCTNUM
  101.                    AND SYMBOL = "GM");
  102.  
  103.      2. SELECT NAME FROM CLIENTS
  104.         WHERE EXISTS
  105.           (SELECT * FROM TRANSACT
  106.              WHERE ACCTNUM = CLIENTS.ACCTNUM
  107.                    AND SYMBOL = "GM");
  108.  
  109.      Note the presence of "EXISTS" or "NOT EXISTS", they make the
  110.      predicate existential.  Also note the nested subquery
  111.      "(SELECT * ..." and the local predicate "AND SYMBOL='GM', a
  112.      predicate which is confined, or local, to the table     
  113.      referenced in the subquery.  If the above conditions exist and
  114.      Also, if the table in the subquery, TRANSACT has more than 5,000,
  115.      the anomaly may occur (it won't always).
  116.      
  117. WORK-AROUND:
  118.  
  119.      Split the query into two queries, storing intermediate
  120.      results in a temporary table.
  121.  
  122.      
  123.      SELECT * FROM TRANSACT 
  124.        WHERE "GM" = trim(SYMBOL) SAVE TO TEMP T1;
  125.      SELECT NAME FROM CLIENTS 
  126.        WHERE EXISTS
  127.         (SELECT * FROM T1 WHERE ACCTNUM = CLIENTS.ACCTNUM);
  128.  
  129.      
  130. c)   If a query contains a two-table join,
  131.         AND a local predicate on the join column,
  132.         AND both join columns are indexed,
  133.  
  134.      then the user MAY get an "Internal Error".  
  135.  
  136. EXAMPLE:
  137.  
  138.      SET SQL ON
  139.      START DATABASE SAMPLES;
  140.      DROP INDEX ORDER_ID;
  141.      DBDEFINE TRANSACT;
  142.      DBDEFINE STOCK;
  143.      CREATE INDEX ORDER_ID ON TRANSACT(ORDER_ID);
  144.      CREATE INDEX ORDERID ON STOCK(ORDER_ID);
  145.      
  146.      SELECT TRANSACT.ORDER_ID FROM TRANSACT, STOCK
  147.          WHERE TRANSACT.ORDER_ID = STOCK.ORDER_ID 
  148.          AND TRANSACT.ORDER_ID = '87-105';
  149.  
  150. WORK-AROUND:
  151.  
  152.      Drop one of the indexes.
  153.  
  154.      Note:  The two-table join (WHERE TRANSACT.ORDER_ID =
  155.      STOCK.ORDER_ID), the indexes on both joined columns, and the
  156.      predicate condition local to the TRANSACT table.  Dropping either
  157.      index will allow the query to succeed.
  158.  
  159.