Solved! Go to Solution.
import arcpy from arcpy import env # Define workspace env.workspace = "C:/PythonParcelProcesses" # paths to tables masterTable = 'UpdateInsertTo.dbf' subsetTable = 'UpdateInsertFrom.dbf' # define fields: keyField = 'APN' testFields = ['APN_SUFFIX', 'TRA', 'NAME_1', 'NAME_2', 'MAIL_ADDR', 'CTY_STA'] # dictionary of the contents of the subset table # APN is key, fields to test are stored in an ordered list subsetDict = {} sC = arcpy.SearchCursor(subsetTable) for row in sC: subsetDict[row.getValue(keyField)] = [row.getValue(field) for field in testFields] del sC, row # get list of values that need to be updated updateDict = {} sC = arcpy.SearchCursor(masterTable) for row in sC: key = row.getValue(keyField) testList = [row.getValue(field) for field in testFields] # try to get record in subsetDict to see if it has changed # if the subset table didn't contain a record for this entry, will trow KeyError (that's fine - do nothing) try: # if records have changed add to updateDict and delete from subsetDict if subsetDict[key] != testList: updateDict[key] = subsetDict[key] del subsetDict[key] # records are the same, delete from subsetDict else: del subsetDict[key] except KeyError: # this APN only exists in the master table, do nothing... pass del sC, row # anything left in subsetDict is new, can use insertCursor iC = arcpy.InsertCursor(masterTable) for key in subsetDict: row = iC.newRow() row.setValue(keyField, key) for i in range(len(testFields)): field = testFields row.setValue(field, subsetDict[key]) iC.insertRow(row) del row del iC # anything in updateDict needs to be updated, use updateCursor uC = arcpy.UpdateCursor(masterTable) for row in uC: key = row.getValue(keyField) if row.getValue(keyField) in updateDict: for i in range(len(testFields)): field = testFields row.setValue(field, updateDict[key]) uC.updateRow(row) del uC, row, updateDict, subsetDict
import arcpy # paths to tables masterTable = '//masterTable' subsetTable = '//subsetTable' # define fields: keyField = 'APN' testFeild1 = 'a' testField2 = 'b' #... and so on ## If you know all your fields and will never need to change them I would recommend using the 'dynamic' noation row.APN inseatd of row.getValue('APN') as I have used below # dictionary of the contents of the subset table # APN is key, fields to test are stroed in an ordered list subsetDict = {} sC = arcpy.SearchCursor(subsetTable) for row in sC: subsetDict[row.getValue(keyField)] = [row.getValue(testField1), row.getValue(testField2)] del sC, row # get list of values that need to be updated updateDict = {} sC = arcpy.SearchCursor(masterTable) for row in sC: key = row.getValue(keyField) testList = [row.getValue(testField1), row.getValue(testField2)] # if records have changed add to updateDuct and delete from subsetDict if subsetDict[key] != testList: updateDict[key] = subsetDict[key] del subsetDict[key] # records are the same, delete from subsetDict else: del subsetDict[key] del sC, row # anything left in subsetDict is new, can use insertCursor iC = arcpy.InsertCursor(masterTable) for key in subsetDict: row = iC.newRow() row.setValue(keyField, key) row.setValue(testField1, subsetDict[key][0]) row.setValue(testField2, subsetDict[key][1]) iC.insertRow(row) del row del iC, subsetDict # anything in updateDuct needs to be updated, use updateCursor uC = arcpy.UpdateCursor(masterTable) for row in uC: if row.getValue(keyField) in updateDict: row.setValue(testField1, updateDict[key][0]) row.setValue(testField2, updateDict[key][1]) del uC, row, updateDict
if subsetDict[key] != testList: updateDict[key] = subsetDict[key] del subsetDict[key] # records are the same, delete from subsetDict else: del subsetDict[key] del sC, row
import arcpy from arcpy import env # Define workspace env.workspace = "C:/PythonParcelProcesses" # paths to tables masterTable = 'UpdateInsertTo.dbf' subsetTable = 'UpdateInsertFrom.dbf' # define fields: keyField = 'APN' testField1 = 'APN_SUFFIX' testField2 = 'TRA' testField3 = 'NAME_1' testField4 = 'NAME_2' testField5 = 'MAIL_ADDR' testField6 = 'CTY_STA' #... and so on ## If you know all your fields and will never need to change them I would recommend using the 'dynamic' notation row.APN instead of row.getValue('APN') as I have used below # dictionary of the contents of the subset table # APN is key, fields to test are stored in an ordered list subsetDict = {} sC = arcpy.SearchCursor(subsetTable) for row in sC: subsetDict[row.getValue(keyField)] = [row.getValue(testField1), row.getValue(testField2), row.getValue(testField3), row.getValue(testField4), row.getValue(testField5), row.getValue(testField6)] del sC, row # get list of values that need to be updated updateDict = {} sC = arcpy.SearchCursor(masterTable) for row in sC: key = row.getValue(keyField) testList = [row.getValue(testField1), row.getValue(testField2), row.getValue(testField3), row.getValue(testField4), row.getValue(testField5), row.getValue(testField6)] # if records have changed add to updateDict and delete from subsetDict if subsetDict[key] != testList: updateDict[key] = subsetDict[key] del subsetDict[key] # records are the same, delete from subsetDict else: del subsetDict[key] del sC, row # anything left in subsetDict is new, can use insertCursor iC = arcpy.InsertCursor(masterTable) for key in subsetDict: row = iC.newRow() row.setValue(keyField, key) row.setValue(testField1, subsetDict[key][0]) row.setValue(testField2, subsetDict[key][1]) row.setValue(testField3, subsetDict[key][2]) row.setValue(testField4, subsetDict[key][3]) row.setValue(testField5, subsetDict[key][4]) row.setValue(testField6, subsetDict[key][5]) iC.insertRow(row) del row del iC, subsetDict # anything in updateDict needs to be updated, use updateCursor uC = arcpy.UpdateCursor(masterTable) for row in uC: if row.getValue(keyField) in updateDict: row.setValue(testField1, updateDict[key][0]) row.setValue(testField2, updateDict[key][1]) row.setValue(testField3, updateDict[key][2]) row.setValue(testField4, updateDict[key][3]) row.setValue(testField5, updateDict[key][4]) row.setValue(testField6, updateDict[key][5]) del uC, row, updateDict
# get list of values that need to be updated updateDict = {} sC = arcpy.SearchCursor(masterTable) for row in sC: key = row.getValue(keyField) testList = [row.getValue(testField1), row.getValue(testField2), row.getValue(testField3), row.getValue(testField4), row.getValue(testField5), row.getValue(testField6)] # try to get record in subsetDict to see if it has changed # if the subset table didn't contain a record for this entry, will trow KeyError (that's fine - do nothing) try: # if records have changed add to updateDict and delete from subsetDict if subsetDict[key] != testList: updateDict[key] = subsetDict[key] del subsetDict[key] # records are the same, delete from subsetDict else: del subsetDict[key] except KeyError: # this APN only exists in the master table, do nothing... pass del sC, row
The master table is now being updated with new rows from the subset table
Strangely the first new row is being placed last in the master table
and a KeyError is being called on its key field value
and, although a print command placed after the last line confirms that the script is completing, the insertCursor block does not seem to be working.
Do you mean: 1. 'the new rows are being added at the end', or 2. ' the top-most new row is bottom-most in the updated table'? Either way:
1. The InsertCursor adds a new row to the bottom of the table, so this is expected.
2. Dictionary keys are not actually ordered; so the order in which the rows are added to the table is (effectively) random.
I need more detail on this.
A KeyError means that it is asking the dictionary for a key that doesn't exist. Which block is this occurring in?
If the Insert Cursor is not working, new rows would not be being added from the subset table (your first comment) - do you mean the Update Cursor?
Mark,
can you send me the files you are testing with (you can attach files to posts)? If you have to, zip them together.
I just can't figure what the problem might be without being able to test stuff and see it for myself.
Stacy