pythonsqlsqlite

Filling Null values ​in sqlite3 with the value of the same row but the next column in python


I have a database in sqlite, now when inserting into this data, some spaces are defined as null. I need a script that finds nulls and puts the value of the same row but the next column in null to be filled (the value on the right).
in python
Screenshot of database table

# Fetch all data from your table
cursor.execute("SELECT * FROM my_table")
rows = cursor.fetchall()

# Get the column names
column_names = [description[0] for description in cursor.description]

# Loop through each row and update NULL values
for row in rows:
    # Prepare the data to be updated
    updated_row = list(row)

    # Replace NULL values with the value to the right
    for i in range(len(updated_row) - 1):
        if updated_row[i] is None:
            # Find the next non-NULL value to the right
            for j in range(i + 1, len(updated_row)):
                if updated_row[j] is not None:
                    updated_row[i] = updated_row[j]
                    break

    # Update the row in the database
    update_query = f"UPDATE your_table_name SET {', '.join(f'{col} = ?' for col in column_names)} WHERE rowid = ?"
    cursor.execute(update_query, (*updated_row, row[0]))  # Assuming the first column is the rowid

but i have This Error:

   cursor.execute(update_query, (*updated_row, row[0]))  # Assuming the first column is the rowid
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sqlite3.OperationalError: near "20553975": syntax error

Solution

  • Okay there's a few issues here. First of all, as pointed out in the other answer, numeric column names are a no-no. You can use them, but it's discouraged and might lead to unexpected behaviors. The easiest way to fix this would be to wrap them in backticks so you'd get ', '.join(f'`{col}` = ?' for col in column_names).

    Though in general, it'd be much preferable to only update columns that actually change. So consider

    cursor.execute("SELECT * FROM my_table")
    rows = cursor.fetchall()
    column_names = [description[0] for description in cursor.description]
    
    # you only need to count once
    colcount = len(column_names)
    
    for row in rows
        # Use a dict to store the columns that need changing and their values.
        # Nowadays the dict() builtin provides an OrderedDict, which has benefits
        updated_row = dict()
        # Only update nulls
        for i in range(colcount):
            if row[i] is None:
                j = i + 1
                while j < colcount:
                    # check the next column if available
                    if row[j] is not None:
                        updated_row[column_names[i]] = row[j]
                        break
                    j += 1
                # if break is never called, there is no non-null. Default to 0
                else:
                    updated_row[column_names[i]] = 0
    
        update_query = f"""
                       UPDATE your_table_name
                       SET {', '.join(f'`{col}` = ?' for col in updated_row)}
                       WHERE rowid = ?
                       """
        cursor.execute(update_query, (*updated_row.values(), row[0]))