0

I want to insert data with type(bytes) into Oracle table into column raw(16) using Python.

INFO - this is data which I want to insert:

('1', "'test'", "to_date('2021-09-28 15:31:02','YYYY-MM-DD HH24:MI:SS')", b'\xb5V\xad\x04E\xd3V\x1b\x04B\xedL]~W\xf5')

But I have errors

sql = f"INSERT /*+ APPEND */ INTO {table} {target_fields} VALUES  ({','.join(values)})"
    

TypeError: sequence item 3: expected str instance, bytes found

This is my code:

def get_md5(d):
       b = pickle.dumps(d)
        return hashlib.md5(b).digest()
    
for row in rows:
    i += 1
    lst = []
    for cell in row:
        if isinstance(cell, str):
            lst.append("'" + str(cell).replace("'", "''") + "'")
        elif cell is None:
            lst.append('NULL')
        elif isinstance(cell, float) and numpy.isnan(cell):  # coerce numpy NaN to NULL
            lst.append('NULL')
        elif isinstance(cell, numpy.datetime64):
            lst.append("'" + str(cell) + "'")
        elif isinstance(cell, datetime):
            lst.append(
                "to_date('" + cell.strftime('%Y-%m-%d %H:%M:%S') + "','YYYY-MM-DD HH24:MI:SS')"
            )
        else:
            lst.append(str(cell))
    lst.append("to_date('" + datetime.now().strftime('%Y-%m-%d %H:%M:%S') + "','YYYY-MM-DD HH24:MI:SS')")
    s = get_md5(lst)
    lst.append(s)
    
    values = tuple(lst)

    print('values', values)
    sql = f"INSERT /*+ APPEND */ INTO {table} {target_fields} VALUES  ({','.join(values)})"
    print(sql)
    cur.execute(sql)

5
  • Never build an SQL query using string concatenation. Use a prepared statement INSERT INTO table_name (col1, col2, col3) VALUES (?, ?, ?) and then use bind variables to pass the values. Commented Sep 28, 2021 at 10:01
  • @MT0 it is default Oracle_Hook scrpt in Airflow. I just wanted to add extra BYTES column Commented Sep 28, 2021 at 10:03
  • As being more performant for the DML statements, prefer using executemany rather than execute. Commented Sep 28, 2021 at 14:33
  • @BarbarosÖzhan Ok. but my problem is inserting bytes with string into table Commented Sep 28, 2021 at 15:35
  • consider that as a side note, not directly related to your current problem. Commented Sep 28, 2021 at 16:28

1 Answer 1

1

Use bind variables. Something like this:

def get_md5(d):
       b = pickle.dumps(d)
        return hashlib.md5(b).digest()
    
for row in rows:
    i += 1
    lst = [cell for cell in row]
    lst.append(get_md5(lst))
    
    print('values', lst)

    sql = (
        f"INSERT /*+ APPEND */ INTO {table} {target_fields}"
        f" VALUES ({','.join([f':{field}' for field in target_fields])})"
    )

    print(sql)

    cur.execute(sql, lst)

As the linked documentation states:

Using bind variables is important for scalability and security. They help avoid SQL Injection security problems because data is never treated as part of an executable statement. Never concatenate or interpolate user data into SQL statements.

(Emphasis mine)

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! I changed my code. And now insert looks like this INFO - INSERT /*+ APPEND */ INTO DWH_STAGE2.ZZ_TEST_ARFLOW (REGION_ID, REGION_NAME, S$CHANGE_DATE, S$MD5) VALUES (:REGION_ID, :REGION_NAME, :S$CHANGE_DATE, :S$MD5) But I have same problems TypeError: sequence item 3: expected str instance, bytes found ins_r = ', '.join(lst) cur.execute(sql, ins_r) when I want to execute it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.