Select to view content in your preferred language

Trouble with UpdateCursor.updateRow()

2585
5
Jump to solution
04-07-2013 11:04 AM
JeremyRead
Emerging Contributor
I am trying to update an SDE feature class based on another SDE feature class using an Update Cursor.  Th feature classes have identical fields and the same number of records.  There is a "LASTMODIFIED" date field that is changed anytime a record is updated in the source feature class. 

What I'm doing is matching up the rows in each table using their "ID" field, then checking to see if the "LASTMODIFIED" date is different.  If it is different, then I want to update the entire row of the target feature class with the row from the source feature class.

For some reason, this is not working.  The script runs without error, and I've inserted counters to make sure it is finding cases where the last modified dates are different (it is).  However, when I check the records of the target dataset after the script has run, no data has been changed at all.

Does anyone know why this is happening?  I want the entire record to be replaced with the source FCC record, and I thought updateRow() would do that.  The only other thing I can think of is to delete the existing record and insert the record I want in its place, but that seems kind of stupid to me.

sourceFCCur = arcpy.UpdateCursor(SourceFCPath) for sourceFCRow in sourceFCCur:     targetFCCur = arcpy.UpdateCursor(TargetFCPath)     for targetFCRow in targetFCCur:         if targetFCRow.ID == sourceFCRow.ID:             sourceFCDate = sourceFCRow.getValue('LASTMODIFIED')             targetFCDate = targetFCRow.getValue('LASTMODIFIED')             if sourceFCDate != targetFCDate:                 targetFCCur.updateRow(targetFCRow)     del targetFCCur
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
ArkadiuszMatoszka
Frequent Contributor
Hi,
If you'll look at lines below (from your code) you will notice that you're overwriting row with itself, so i wouldn't expect any change in data:

targetFCCur = arcpy.UpdateCursor(TargetFCPath)     for targetFCRow in targetFCCur:         ... nothing with targetFCRow done here ...         targetFCCur.updateRow(targetFCRow)


You should copy each field value from source row to target row, it won't happen by itself.

Regards
Arek

View solution in original post

0 Kudos
5 Replies
ArkadiuszMatoszka
Frequent Contributor
Hi,
If you'll look at lines below (from your code) you will notice that you're overwriting row with itself, so i wouldn't expect any change in data:

targetFCCur = arcpy.UpdateCursor(TargetFCPath)     for targetFCRow in targetFCCur:         ... nothing with targetFCRow done here ...         targetFCCur.updateRow(targetFCRow)


You should copy each field value from source row to target row, it won't happen by itself.

Regards
Arek
0 Kudos
RaphaelR
Deactivated User
like arek said, you have to get the values of your source FC and update the corresponding fields in the target FC.
something like this should work (only tested with a small sample of data), or at least help get you started:

import arcpy

source = "E:/test.mdb/src"
target = "E:/test.mdb/trg"

# cursor for sourceFC
s_rows = arcpy.SearchCursor(source)
# Dictionary for sourceFC´s fields
sDict = {}
# field names of sourceFC/targetFC, excluding Shape and OID
fList = [a.name for a in arcpy.ListFields(source) if a.name not in ("OBJECTID","Shape")]

# fill the sourceFC Dict(OIDs as keys) with dictionaries of its fieldnames/values
for s_row in s_rows:
    sDict[s_row.OBJECTID] = dict((k,s_row.getValue(k)) for k in fList)
del s_row,s_rows

# update cursor for targetFC
t_rows = arcpy.UpdateCursor(target)
for t_row in t_rows: 
    # compare the current row's field with the corresponding one from the sourceFC-dict
    # if values differ, update all target fields with sourceFC-dict´s values
    if t_row.LASTMODIFIED != sDict[t_row.OBJECTID]["LASTMODIFIED"]:
        for fName in fList:
            t_row.setValue(fName, sDict[t_row.OBJECTID][fName])
    t_rows.updateRow(t_row)
    
del t_row,t_rows
0 Kudos
JeremyRead
Emerging Contributor
Many thanks to both of you for your help.

I see what you mean about overwriting a row with itself.  That was a typo on my part as I was trying to change the names of the variables to be more generic/readable in the post, so my apologies on that.  The actual script was trying to read the row from the other cursor:  targetFCCur.updateRow(sourceFCRow)

Raphael, thank you for the example you posted.  One question: what can I do to retain the shape information since it cannot be included in the dictionary?  All the other fields will need to be copied, but the shape will also need to be transferred.

At the moment, I've decided to just delete the existing record and insert the updated record instead.  It's not ideal, but it is working ok if nothing else works.
0 Kudos
ArkadiuszMatoszka
Frequent Contributor
If you're using arcgis 10.1 I would suggest using arcpy.da.UpdateCursor instead of arcpy.UpdateCursor.
It much faster and offers easy access to geometry (simply add 'SHAPE@' to field list), disadvantage is its less intuitive at the beginning.

Regards,
Arek
0 Kudos
RaphaelR
Deactivated User
changed the code a bit to update the shape field of the targetFC as well. works for me if the FCs are point-type.

import arcpy

source = "E:/test.mdb/src"
target = "E:/test.mdb/trg"

# cursor for sourceFC
s_rows = arcpy.SearchCursor(source)
# Dictionary for sourceFCs fields
sDict = {}
# field names of sourceFC/targetFC, excluding Shape and OID
fList = [a.name for a in arcpy.ListFields(source) if a.name not in ("OBJECTID","Shape")]

# fill the sourceFC Dict(OID as key) with dictionaries of its fieldnames/values
for s_row in s_rows:
    sDict[s_row.OBJECTID] = dict((k,s_row.getValue(k)) for k in fList)
    
    # get point coordinates from the shape field and put them into the dict
    s_pnt = s_row.Shape.getPart()
    sDict[s_row.OBJECTID]["GEO"] = (s_pnt.X,s_pnt.Y)    
del s_row,s_rows
print sDict

# update cursor for targetFC
t_rows = arcpy.UpdateCursor(target)

for t_row in t_rows: 
    # compare the current row's field with the corresponding one from the sourceFC-dict
    # if values differ, update all target fields with sourceFC-dicts values
    if t_row.LASTMODIFIED != sDict[t_row.OBJECTID]["LASTMODIFIED"]:
        for fName in fList:
            t_row.setValue(fName, sDict[t_row.OBJECTID][fName])
            
            # replace point coordinates of shape field with values from the sourceFC-dict
            t_pnt = arcpy.Point(sDict[t_row.OBJECTID]["GEO"][0],sDict[t_row.OBJECTID]["GEO"][1])
            t_row.setValue("Shape", t_pnt)
    t_rows.updateRow(t_row)
    
del t_row,t_rows
0 Kudos