-
Notifications
You must be signed in to change notification settings - Fork 359
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Batch-inserting via executemany() fails with NotSupportedError: Python value cannot be converted to a database value #236
Comments
Thanks for the detailed explanation of the issue you are experiencing. I'll take a look and let you know if I am able to reproduce the issue. |
@anthony-tuininga thank you. I appreciate that very much. I managed to reproduce the issue on a complete seperate environment (seperate from our corporate Windows Environment). On my linux home computer, I setup a linux container and installed the free Oracle Express Edition Server 11.2.0-1.0 on Archlinux with Kernel 4.14.78-1-lts (amd64). As client, I used Archlinux on another machine with python 3.7.1, cx_Oracle 7.0.0 and Oracle Instant Client (Basic Package) 18.3.0.0.0 Note: Using the dataset from above on linux, I ran into some utf-8 encoding issues, that I don't think is relevant here, so I replaced the problematic contents with randomized data and uploaded a new dataset |
I am having the exact same problem with similiar coding. If I limit the blocksize to 1 it works perfect albeit very slow |
I am able to reproduce the issue using your data set. I'll get back to you on why this is happening. |
I now understand why this is happening. In your first batch two of your columns never have any value other than None. cx_Oracle defers type assignment until the end of the batch and then simply assumes None is the only value possible (string with maximum length 1). In your second batch at least one of the rows actually has a value, but that value isn't compatible. The error message is very misleading, however, so I'll see if I can address that. You have a few options: (1) perform all inserts in a single batch (but depending on size this might not be usable) Of those three options, the second option is the simplest and will only add a small bit of overhead. The third option is the one you'll want to use for the best performance. |
Just for clarity, here is a simple test case that demonstrates the issue: import cx_Oracle
conn = cx_Oracle.connect("cx_Oracle/welcome")
cursor = conn.cursor()
cursor.execute("truncate table TestTempTable")
sql = "insert into TestTempTable values (:1, :2)"
cursor.executemany(sql, [(1, None), (2, None)])
cursor.executemany(sql, [(3, None), (4, "Testing")]) The second call to executemany() will fail with the error you reported. |
…olumns that are always null and a subsequent call to cursor.executemany() has a value other than None in the same column (#236).
I've just added a commit that should correct this issue and added a test case as well. Let me know if that addresses your issue. Thanks! |
@anthony-tuininga thank you very much. I don't have the possibility to install cx_Oracle from source in our environment, but I will happily await till it gets packaged for my distribution. meanwhile I will try out your workaround number 2) and create a new cursor for each batch. Thanks a lot :-) |
Corrected in cx_Oracle 7.1 which was released yesterday. |
Reproduced in cx_oracle 7.1.3 |
In the same batch of data that you pass to cx_Oracle, yes, you will get an exception. That is expected. The bug that was fixed was regarding the use of all null values in one batch followed by a numeric value in a subsequent batch. |
no you missunderstand me, It cannot be expected behaviour. |
@omrumcetin To avoid misunderstandings please show (complete) runnable code that has the problem and the SQL to create the schema. If you have one column and it is defined as a number, why are you trying to insert a string, or vice versa? Review Batch Statement Execution and Bulk Loading. The section on defining memory areas is worth careful study. |
I'm defining VARCHAR2 because inserted value sometimes can be number, sometimes can be a string. Its very common stuff. |
Can you provide a link to the documentation that suggests this case should be supported? cx_Oracle doesn't attempt to perform any conversions from number to string or from date to string -- and I believe that is the right approach. You can use a variable converter function if you wish to perform any conversions -- but generally it is just better to ensure that the data is available in a uniform fashion. |
Batch-inserting via executemany() fails with
NotSupportedError: Python value cannot be converted to a database value
Batch-inserting many rows in chunks of 1000, 500, 100, 50, 20, 10 via executemany() fails with
NotSupportedError: Python value cannot be converted to a database value
If I insert every row line by line, it works.
maybe similar problem as in
https://stackoverflow.com/questions/50713180/cx-oracle-notsupportederror-python-value-cannot-be-converted-to-a-database-valu
Oracle Server
Oracle Database 12c Standard Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production
CORE 12.1.0.2.0 Production
TNS for 64-bit Windows: Version 12.1.0.2.0 - Production
NLSRTL Version 12.1.0.2.0 - Production
Client Software
Client OS: Windows 7 Pro 64bit
Python 3.6.7, 64bit (via Anaconda)
cx_Oracle 7.0.0
Oracle Client Version: 11.2.0.1.0
(determined via https://stackoverflow.com/questions/1171643/whats-the-best-way-to-determine-which-version-of-oracle-client-im-running)
Windows PATH:
Steps to reproduce
Download sample dataset, see attached file 01_data_anonymous.zip
https://github.com/oracle/python-cx_Oracle/files/2567112/01_data_anonymous.zip
Extract sample dataset
01_data_anonymous.zip
to file01_data_anonymous.pckl
Run sample code:
Outputs:
The text was updated successfully, but these errors were encountered: