Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

VFP 6 SET SKIP Problem

Status
Not open for further replies.

ewachs2

Technical User
Jun 25, 2006
5
US
I've never needed to use the SET SKIP TO command until this weekend.

The bottom line, I'm guessing that my understanding is incorrect or I'm not following the examples I've found closely enough.

From reading various sites, VFP help, etc. I've come to believe that if you properly set the relation and properly
issue the SET SKIP command, as VFP scans through the parent table it sort of creates phantom/virtual extra rows
to correspond with those child table rows that create a one-to-many situation.
In other words, the parent table pointer stays on the parent record until the multiple child records
have been cycled through.

I've spent hours trying to figure out how I've screwed this up but have a hit a brick wall. I can't get SET SKIP to work in my effort to add data from the fields of a parent table to fields of a child table on those records that represent a one-to-many relationship. I'm sure it's something simple and obvious but I'm surely overlooking whatever is staring me in the face.

Following the code are things I've tried and other pertinent information.

Your help will be greatly appreciated.

The environment:
SET CONFIRM ON
SET DELETED ON
SET EXACT ON
SET LOGERROR ON
SET STATUS OFF
SET TALK OFF


The code:
Code:
PROCEDURE procedure_name

  USE child_table in 1 ALIAS child_table

  USE parent_table IN 2 ALIAS parent_table
  SELE parent_table
  SET ORDER TO   

  * extract the date of the last records appended to the parent table in text format from field 1
  GO BOTT
  date_text_ = SUBSTR(field1,1,6)
  SET ORDER TO field1

  SET RELATION TO parent_table.field1 INTO child_table ADDITIVE

  SELECT parent_table  && probably superflous here
  SET SKIP TO child_table

  SET EXACT OFF
  SEEK date_text_
  SET EXACT ON

  SCAN WHILE date_text_ $ field1
	
	* I've tried to replace field contents two ways (they each appear to work for one-to-one relationship but not one-to-many)
	
	* this was the first
		REPLACE child_table.horse_id   with parent_table.horse_id,   ; 
				child_table.country    with parent_table.country,    ; 
				child_table.comb_alpha with parent_table.comb_alpha, ;
				child_table.alpha_only with parent_table.alpha_only, ;
				child_table.trainer_r  with parent_table.trainer_r,  ;
				child_table.train_id   with parent_table.train_id 
	
	
	
	* this was the second
		REPLACE horse_id   with parent_table.horse_id,   ; 
				country    with parent_table.country,    ; 
				comb_alpha with parent_table.comb_alpha, ;
				alpha_only with parent_table.alpha_only, ;
				trainer_r  with parent_table.trainer_r,  ;
				train_id   with parent_table.train_id IN child_table
	
  ENDSCAN
 
RETURN

Some other potentially pertinent facts:
I'm using VFP 6

These test tables have several hundred thousand records. The actual tables will have millions.

The example above does not work with even 1 child table. The real example has 6 child tables and they were named in the one SET SKIP TO command with commas separating them.

The parent table always has unique records.
Not every record in the parent table has a corresponding record in the child tables, depending upon the particular child table, perhaps 5% to 85% of the parent table records have a corresponding child table. The single child table example I've been working with trying to solve this problem has about 85%.

The field used to set the relation (in the example above, called field1) has been double checked in both parent and child tables using the MODIFY STRUCTURE command and they are identical character fields with a length of 14 characters.

The indeces on the field used to set the relation created in the parent and child tables have the identical form of ALLTRIM(field1)

As a cross check, when what is the child table in the example above is viewed without having related it to the parent; i.e., not a child in this particular cross check case, just as an independent check of the index, those "children" with multiple records do appear in the correct sort order based on the index, one below the other

It has worked flawlessly with SET RELATION; i.e., prior to having to add an occasional second record for an account in the child table.

It still works flawlessly for the first record of an account that has 2 records, only the second record fails to be updated

I've used the expressions "parent_table", "child_table", and "fieldn" for simplicity of the example. The actual table names and field names are valid Foxpro names.

The tables are not and have never been part of a DBC.

The index for each table is part of a structural compound index.

I've packed (and, therefore, re-indexed) both tables used in the example above.

The one-to-many relationship do not appear when a BROWSE command is issued.

The contents of field1 is automatically generated by a program at two separate times, once for the parent table and once for the child table but that code appears to be solid as evidenced by the flawless performance of the SET RELATION COMMAND and my visual inspection of the contents of the fields causing the problem in the child tables.

In the example above, the parent table happens to be ordered on the relational expression of the SET RELATION command. My understanding is that the child table must be ordered on that but the parent table may be ordered on that, on some other field or expression or on nothing.
 
Hi ewachs2,
Your program listing above is great - but it has a few flaws, unfortunately they may have nothing to do with your problem and are probably just an oversight.

The child table in your sample code doesn't have an order set, so the relationship won't work.

Due to the "go bottom", the sample code will only replace data based on the last record in your parent table. Therefore if you were expecting all records in the child table to be replaced with it corresponding parent record, then that won't happen.

I made a little test program (VFP 8) based on your sample code above and it all seemed to work correctly. Looking in the "data session" window I can see that your setting of the one to many relationship does seem to work and my tables updated as I would have expected.

Sorry I couldn't be of more help.
Goodluck,
Shardlow.
 
Shardrow,

Thanks for your time and insights.

I checked the actual code and the child table does, in fact, have the correct order set. Leaving it out of the code above was an oversight. Thanks for noticing.

If I understand the second potential problem you point out, I believe your concern about the GO BOTTOM statement is avoided by the SEEK statement between the SET EXACT statements. Both the GO BOTT and SEEK are acting on the parent table so I believe the SCAN is starting where I need it to.

What I find troubling is that the code seemed to work for you and won't for me.

Is there some setting I could have wrong somewhere?

Also, when I changed computers a couple of years ago, I'm wondering if I completely updated VFP after installation. I'm showing VFP 6.0 SP3 Version: 06.00.8492.00.

Again, thank you.
 
DSummZZZ,

Thank you for your good idea. Unfortunately, that was among the first things I checked. There are only 2 parent records that have a one-to-many relationship with the child table and both of those parent records are present. Of course ,the child records are present (that's how I know I have a problem. I also checked the relational expressions used by the SET RELATION command and they are present and identical in both tables (I just double checked all of the above facts in an abundance of caution on the chance I wasn't careful enough originally).

The program works fine one-to-one - all records that are one-to-one between the tables get updated, but if more than one corresponding record is in the child table, only the earliest appended record gets updated and those that create the one-to-many relationship - those that the SET SKIP TO command is designed for - don't.

If you believe, as Shardlow does, that the code above is correct (i.e., assuming I have the SET ORDER command in the original code that Shardlow noticed I forgot to include) I'm guessing it has to be something like your suggestion or some setting of some sort; it just happens not to be the specific suggestion you made above. Thanks, again, for trying.
 
Rather than fight this issue then, I would approach it differently then:
Code:
USE child_table  IN 0 ALIAS child_table ORDER ??????
USE parent_table IN 0 ALIAS parent_table
GO BOTT
date_text_ = SUBSTR(field1,1,6)
SET ORDER TO field1

SET EXACT OFF
SEEK date_text_
SET EXACT ON

SELECT parent
SCAN WHILE date_text_ $ field1
   SELECT child_table
   DO WHILE SEEK(parent.field1)
      REPLACE horse_id   with parent_table.horse_id,   ;
              country    with parent_table.country,    ;
              comb_alpha with parent_table.comb_alpha, ;
              alpha_only with parent_table.alpha_only, ;
              trainer_r  with parent_table.trainer_r,  ;
              train_id   with parent_table.train_id 
   ENDDO
   SELECT parent  &&... this statement not really needed
ENDSCAN

-Dave Summers-
[cheers]
Even more Fox stuff at:
 
Hi ewachs2,
You wrote:
"I believe your concern about the GO BOTTOM statement is avoided by the SEEK statement between the SET EXACT statements."

Based on your sample code, the SEEK statement would just return the record pointer to the last record in the parent table. I am of course assuming that Field1 contains unique values in Parent_Table.

Consider the following example:
Parent_Table
Field1 Horse_id
1 Horse1
2 Horse2

The first part of the code is:
GO BOTT
date_text_ = SUBSTR(field1,1,6)

date_text_ now contains 2


The next part of the code is:
SEEK date_text_

As date_text_ contains 2 the record pointer is returned to the last record in parent_table. Then all the child_table records are processed that have Field1 == 2.

As the sample program doesn't seem to be in a loop this will be the only record processed. As date_text_ cannot be any other value other than 2.


Your set skip command may also not work if your indexes are corrupted. You wrote:
"I've packed (and, therefore, re-indexed) both tables used in the example above."
Note that packing a table does not re-index a table; it just removes the records marked for deletion. Re-indexing of tables must be done seperately.

The 1st thing I would be looking for is to check if the one to many relationship is set. To do this insert the command "SET STEP ON" after the line "SET SKIP TO child_table".
Run the program and when it stops type SET in the command window to bring up the Data Session window. In the relations box there should be two lines like an equal sign to the left of the Child table. If you can see the double lines then your one to many relationship is working.

Goodluck,
Shardlow.
 
baltman,

Yet another good thought but as you can see from the following list of settings, not the source of the problem.

Alternate - on Fullpath - on
ANSI - off Heading - on
Asserts - off Help - on
Bell - on Intensity - on
Blink - on Lock - off
Brstatus - off Logerrors - on
Carry - off Mouse - on
Century - off Multilocks - off
Clear - on Near - off
Color - on Null - off
Compatible - off Optimize - on
Confirm - on Print - off
Console - off Readborder - off
Cursor - on Safety - on
Deleted - on Space - on
Device - scrn Status Bar - on
Echo - off Sysmenus - on
Escape - on Talk - off
Exact - on Textmerge - off
Exclusive - on Title - off
Fields - off Unique - off
Fixed - off

Thanks for the good idea, wish it were the solution.
 
Shardlow and DSummZZZ,

Thanks for your additional thoughts. My work schedule is brutal today. I should have time to try your ideas tomorrow.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top