The Forums on slxdeveloper.com are now retired. The forum archive will remain available for the time being. Thank you for your participation on slxdeveloper.com!
|
|
Table Associations
Posted: 21 Jun 07 1:34 PM
|
Does anyone know where the information for Table associations is?
i.e. Where does DBManger get the information to display AccountProduct as "Associated" to Account with a One To One Relationship
Thanks! Carla |
|
|
|
Re: Table Associations
Posted: 21 Jun 07 1:40 PM
|
Not sure what you are doing bu the metadata is spread around... the join information is in the joindata table, the primarykey information is in sectabledefs, there is also some info in resynctabledefs. |
|
|
|
Re: Table Associations
Posted: 21 Jun 07 1:50 PM
|
Thanks Frank!
I'm trying to write a dynamic script for merging accounts. In some cases I will want to compare fields (1:1 Relationship) in others I will just want to replace accountID (1:Many Relationship OR StandAlones (TBD))
I can get the schema information I need regarding BaseTables and which Tables contain the AccountID (and EntityID!), But I want a little more power to this routine so I won't ever have to touch it again regardless of how many tables I add or delete.
In English - what I need to know:
IF (Table_A is associated to Table_B) AND (AssociatonType = 1:1) THEN Do This ELSEIF (Table_A is associated to Table_B) AND (AssociatonType = 1:Many) THEN Do That ELSE I am a stand alone table but I am tied to main table via ID
END IF
Carla
|
|
|
|
Re: Table Associations
Posted: 22 Jun 07 5:00 AM
|
This will give you a list of tables that have an AcccountID.
SELECT TABLENAME FROM SECTABLEDEFS WHERE FIELDNAME = 'ACCOUNTID'
ws |
|
|
|
Re: Table Associations
Posted: 22 Jun 07 9:02 AM
|
Thanks Walter. Be careful of using that when writing anything dynamic in v7. It also includes Views. You need to move up a level to get any differentiation between Tables and Views.
Carla |
|
|
|
Re: Table Associations
Posted: 22 Jun 07 9:09 AM
|
In English - what I need to know:
IF (Table_A is associated to Table_B) AND (AssociatonType = 1:1) THEN Do This ELSEIF (Table_A is associated to Table_B) AND (AssociatonType = 1:Many) THEN Do That ELSE I am a stand alone table but I am tied to main table via ID
END IF
Carla
|
|
Here is a code snippet from a cascading delete function that I wrote a for use under V5.2. It walks the joins...
sub Gmk_Delete_Related_1(byval argParentTable, byval argParentKey, byval argParentKeyID) nDepth = nDepth + 1 Dim mySQL as String Dim myHnd as Long Dim sChildTable as String Dim sChildField as String Dim sChildKeys as String Dim sKey as String Dim sCascadeType as String Dim nChildCount If argParentTable = "" then goto exit_sub '** Delete any child records mySQL = "SELECT FromTable, FromField, CascadeType FROM JOINDATA" & _ " WHERE Upper(CascadeType) IN ('D','C','S') AND ToTable='" & argParentTable &"'" myHnd = MyDBOpenSQL(mySQL, True) '** For each joined table While DBEof(myHnd) = False sChildTable = DBGetValue(myHnd, "FromTable") sChildField = DBGetValue(myHnd, "FromField") sCascadeType = DBGetValue(myHnd, "CascadeType") sChildKeys = gmk_ChildKeys(sChildTable, sChildField, argParentKeyID) '** Process joined table Select Case sCascadeType Case "D" For nChildCount = 1 to CSVCount(sChildKeys) sKey = CSVField(sChildKeys,nChildCount) Call Gmk_Delete_Related_2(sChildTable, sChildField, sKey) Next nChildCount If sChildKeys <> "" Then DBEXecuteSQL "DELETE FROM " & sChildTable & " where " & sChildField & "='" & argParentKeyID & "'" End If Case "C" If sChildKeys <> "" Then MyDBExecuteSQL "UPDATE " & sChildTable & " set " & sChildField & "=NULL where " & sChildField & "='" & argParentKeyID & "'" End If Case "S" If sChildKeys <> "" Then MyDBExecuteSQL "DELETE FROM " & sChildTable & " where " & sChildField & "='" & argParentKeyID & "'" End If End Select gsPointer = DBMoveTo(myHnd, "Next") Wend DBClose myHnd exit_sub: nDepth=nDepth-1 end sub
|
|
|
|
Re: Table Associations
Posted: 22 Jun 07 9:43 AM
|
Carla, Here are some notes I took on the Cascade type...
' Notes: ' JOINDATA.CascadeType values: ' C=The key field linking the record in the secondary table is ' cleared out, but not the entire record in the secondary table. ' ' D=Delete the selected record and any dependent records ' ' R=When deleting a record, clear out the key field linking the record ' in a secondary table, but not the record itself. ' Replace the key field with another id. ' ' S=(Stop Cascade) ' Delete the selected record, but do not delete any dependent records. ' ' X=(Don't use in cascade) ' When deleting a record, skip this table as If it did not exist.
|
|
|
|
Re: Table Associations
Posted: 22 Jun 07 11:58 AM
|
Thanks Frank!
I think I might be able to work with this. 
Carla |
|
|
|
Re: Table Associations
Posted: 22 Jun 07 12:34 PM
|
Carla, You will need to access the joindata and sectabledefs tables. Joindata to find relationships, and sectabledefs to find primaykey names. Let me if you get hung up. |
|
|
|
Re: Table Associations
Posted: 25 Jun 07 2:34 PM
|
Argh you copier type person. I created a recursive cascadedelete function in 6.1 using VBScript. My function is different because of the parameters I use (tableName, keyField) so it requires a bit of finesse to make the recursion work.
The cool thing about a recursive script is if you change the from and totable, I believe you can recurse up a "tree" as well as down it.
I have a VBScript example that might prove useful:
Public Sub CascadeIterate(TableName) 'Sub ' Simple algorithm to iterate the child relationships of a table
'Syntax ' CascadeIterate(TableName)
'Parameters ' TableName as String - Table in the Database dim objectRecordSet dim stringSQL dim stringFromTable, stringFromKeyField, stringToKeyField, stringCascadeType, stringJoinType dim integerReturn On Error Resume Next integerReturn = 0 if (stringTableName <> "") then ' Match TableName in JoinData stringSQL = "SELECT * FROM JOINDATA WHERE TOTABLE = '" & stringTableName & "' ORDER BY FROMTABLE" set objectRecordSet = GetNewRecordSet(stringSQL) if (objectRecordSet is nothing) then exit sub with objectRecordSet while (not (.EOF)) stringFromTable = .Fields("FROMTABLE").Value stringFromKeyField = .Fields("FROMFIELD").Value stringToKeyField = .Fields("TOFIELD").Value stringCascadeType = .Fields("CASCADETYPE").Value stringJoinType = .Fields("JOINTYPE").Value select case stringCascadeType case "C" case "D" if (stringToKeyField = stringFromKeyField) then integerReturn = MsgBox(Application.Translator.Localize("Calling: CascadeTraverse " & stringFromTable), vbYes, "Validation") CascadeIterate stringFromTable end if case "R" case "S" case "X" case else end select .MoveNext wend .Close end with set objectRecordSet = nothing end if ErrorCheck(Application.Translator.Localize("CascadeIterate:")) On Error Goto 0 End Sub
This sub takes in a table and spits out a MsgBox for each child table it finds. This can be annoying for large hierarchies so you might want to change that. I also use a select statement to deal with cascadetype, with Frank's method probably being better. I wasn't fully aware of the different types and fortunately I only used this function on custom tables which all have type D.
The fun part of a recursive function like this is where to place your custom code so that it executes at the right time. Generally the safe bet is to place it before or after this chunk. |
|
|
|
Re: Table Associations
Posted: 25 Jun 07 2:53 PM
|
Oh, I also use resynctabledefs to find primary keys. Considering that is all that table stores, it's much easier to find them than looking in sectabledefs. The only issue with that is it won't gather non-syncable tables.
Alternatives to this are using SQL's primary keys or gathering it from sectabledefs but there are problems with both methods. With SQL, DBManager doesn't always create the underlying key for custom tables (it never has for us). With sectabledefs there's no easy way of telling which record is the primary key. There's a keyflag column but in our database every record has it as 0. |
|
|
|