postgres insert and update on conflict issue

41 Views Asked by At

I have something I find to be a very strange issue that I cant wrap my head around, I am using psycopg2 with my postgres database (Supabase) - The database is structured as follows: 4 columns: test_col_1 (primary), test_col_2, test_col_3, and test_col_4. All columns are of type "text"

Then I have what becomes my upsert function, below:

#Input variables
f_s_sql_table_name="data_base_name"
f_l_col_names=["primary_col","column_..."]
f_l_t_row_values=[("primary_column_row_value","column_..._row_value")]

#Creates SQL code components
f_s_col_names_sql=", ".join([str(s) for s in list(f_l_col_names)])
f_l_col_names_update=[x+" = excluded."+x for x in f_l_col_names]
f_s_col_names_sql_update=", ".join([str(s) for s in list(f_l_col_names_update)])
f_s_row_values_sql_ph=", ".join(["%s"]*len(f_l_t_row_values))

#Creates SQL code
f_s_sql_input="INSERT INTO "+f_s_sql_table_name+" ("+f_s_col_names_sql+") VALUES "+f_s_row_values_sql_ph+" ON CONFLICT ("+str(f_l_col_names[0])+") DO UPDATE SET "+f_s_col_names_sql_update+";"

#Connects and updates into the database
with psycopg2.connect(**o_sql_config_details) as conn:
    with conn.cursor() as cur:
        
        # execute the INSERT statement
        cur.execute(f_s_sql_input,f_l_t_row_values)

        # commit the changes to the database
        conn.commit()

Now the issue comes when I need to insert a row with a single cell or update a single cell in a specific row, for example below does NOT return an error (test_row_7 exists so this triggers update):

f_s_sql_table_name="test_db"
f_l_col_names=["test_col_1","test_col_2"]
f_l_t_row_values=[("test_row_7","row_test_col_2")]

Neither does the below, which essentially "skips" column 3:

f_s_sql_table_name="test_db"
f_l_col_names=["test_col_1","test_col_2","test_col_4"]
f_l_t_row_values=[("test_row_7","row_test_col_2","row_test_col_4")]

Now however the below DOES return an error (basically I get an error when I skip column 2, but not 3):

f_s_sql_table_name="test_db"
f_l_col_names=["test_col_1","test_col_3","test_col_4"]
f_l_t_row_values=[("test_row_7","row_test_col_3","row_test_col_4")]

The error it throws is below:

NotNullViolation: null value in column "test_col_2" of relation "test_db" violates not-null constraint DETAIL:  Failing row contains (test_row_7, null, row_test_col_3, row_test_col_4).

I am honestly completely lost why this is the case, why do I get an error when I don't include the second column, but not when I do, it is not the primary column and there are nulls in the other columns as well.

Any help is very appreciated here, happy to provide more input - I assume it is something with the way excluded. works, but I am not proficient enough to debug it more than I have already.

EDIT: I found some more information, I for some reason can't set the second column to null (which is why i cant update it with nothing even though it keeps the same, which is a bit weird...) - however, I have no idea why I cant set it to null. Is the second column always special or something?

0

There are 0 best solutions below