I am attempting to do parameterized insert query using pyodbc and Cloudera ODBC Driver for Impala but it is not working.
I am trying to execute the following query.
import pyodbc
insert_query = "insert into table_name(id,name,price) values(?,?,?)"
cursor.execute(insert_query,1,"Apples","20 dollars")
Here is the error I receive:
The SQL contains 0 parameter markers but 3 parameters were supplied, 'HY000'
If I execute the query using Python formatting like this it WORKS:
query_format = "insert into table_name(id,name,price) values({},\"{}\",\"{}\")".format(1,"Apples","20 dollars")
cursor.execute(query_format)
But I really want to specify parameters separately because I would want to do cursor.executemany() to do batch inserts later on and using the formatting approach forces me to use for loop.
Instead of sending values separately , I used tuple too , a list too. Nothing works. Why is it not recognizing "?" as a parameter marker?
Python - 3.7.4,
Pyodbc - 4.0.27,
Anaconda - 1.7.2,
OS - Windows 10
As resolved on GitHub here, this is an issue with the ODBC driver in question, not a problem with pyodbc.
Related
I am struggling to access the results of a stored procedure giving me the identity of the row just inserted using Turbodbc 4.1.2, Python 3.7, and SQL Server 2017.
My procedure runs along the following lines:
CREATE OR ALTER PROCEDURE [dbo].[testSP] #var INT
AS
INSERT INTO testTable VALUES (#var)
SELECT 4 --intermediate step to prove concept
--SELECT SCOPE_IDENTITY() as [scope_id] --final goal
--SELECT ##IDENTITY AS '[scope_id]'
My Turbodbc code looks like this:
cnxn = connect(driver='{ODBC Driver 17 for SQL Server}', server=srv, database=db, uid=user, pwd=password, turbodbc_options=options)
crsr = cnxn.cursor()
cmd = "EXEC testSP 1"
crsr.execute(cmd)
df = pd.DataFrame(crsr.fetchallnumpy())
When running the stored procedure without any inserts (ie, just "SELECT 4"), the result set returns fine. However, when running with the insert, which operates correctly, I receive an error "turbodbc.exceptions.InterfaceError: No active result set". The query runs fine in SSMS.
I am guessing that this is because I am receiving two result sets back - one for the insert, and one for the select. I saw from a couple questions on SO that nextset function is available in pymssql and pyodbc, but that the same functionality is not available in turbodbc.
How can I access the second part in my multi-statement query using turbodbc? This seems like a relatively simple issue, but I have been banging my head against the wall for a few hours.
I am struggling with
pyodbc.ProgrammingError: ('String data, right truncation: length 636 buffer 510', 'HY000')
while using executeMany() with __crsr.fast_executemany = True. When I remove this line everything works fine.
I am using pyodbc (4.0.30) and MSSQL with ODBC Driver 17 for SQL Server.
My database table looks like 4 columns and each of them is varchar(255).
I already to add this line: crsr.setinputsizes([(pyodbc.SQL_WVARCHAR, 50, 0)]) and add UseFMTOnly=yes to connection string but it didn't work.
Could you guys help me, please? I am already tired of that.
Check the ODBC Driver you are using in your pyodbc connection string, if it is an old version, errors could be misleading, use for example:
driver="{ODBC Driver 17 for SQL Server}"
instead of:
driver="{SQL Server}"
Help me to understand if I can parameterize my connection string for a pyodbc connection to this qodbc interface for QuickBooks:
pyodbc.connect(r'DSN=qremote_dsn;IPAddress=192.168.0.50;Port=4500;RemoteDSN=login_dsn;OpenMode=F;OLE DB Services=-2;', autocommit=True)
I have several different DSNs, RemoteDSNs and servers which I'd like to loop over. Several SO posts (here and here) point to this code.google documentation suggesting I can use strings, keywords, or both with pyodbc's connect function.
pyodbc works with many different odbc APIs, so how do determine if any of the pyodbc keywords will map to my required qodbc keywords?
My search for the qodbc keywords in the pyodbc documentation returns no results. Must I conclude f-strings are my only option?
Must I conclude f-strings are my only option?
Not at all.
pyodbc is built to deal with any ODBC driver, so it does not identify which keywords are "legal" and which ones arent. As explained here there are a few keywords that are specified by the DBAPI spec, and a few keywords reserved for pyodbc internal use, and they "are not passed to the odbc driver" implying that other keywords are passed to the ODBC driver.
Example: When I use this connect call ...
cnxn = pyodbc.connect(
driver="ODBC Driver 17 for SQL Server",
server="192.168.0.179,49242",
database="myDb",
uid="sa", pwd="_whatever_",
trusted_connection="no"
)
... the ODBC trace shows that this is the connection string passed to the driver
[ODBC][2404][1589493655.363466][SQLDriverConnectW.c][290]
Entry:
Connection = 0xf7d9c0
Window Hdl = (nil)
Str In = [driver=ODBC Driver 17 for SQL Server;server=192.168.0.179,49242;database=myDb;uid=sa;pwd=_whatever_;trusted_connection=no;][length = 122 (SQL_NTS)]
Note that trusted_connection is specific to SQL Server.
I'm trying to use OPENJSON in a Python script to import some basic JSON into a SQL database. I initially tried with a more complex JSON file, but simplified it for the sake of this post. Here's what I have:
sql_statement = "declare #json nvarchar(max) = '{\"name\":\"James\"}'; SELECT * FROM OPENJSON(#json) WITH (name nvarchar(20))"
cursor.execute(sql_statement)
cursor.commit()
connection.close()
The error I receive:
pypyodbc.ProgrammingError: (u'42000', u"[42000] [Microsoft][ODBC SQL
Server Driver][SQL Server]Incorrect syntax near the keyword 'with'. If
this statement is a common table expression, an xmlnamespaces clause
or a change tracking context clause, the previous statement must be
terminated with a semicolon.")
Any thoughts on why I'm seeing this error? I was successfully able to execute other SQL queries with the same pypyodbc / database configuration.
The problem could be that your database is running in an older compatibility level, where OPEN JSON is not available.
To find the compatibility level of your database, run following SQL statement:
SELECT compatibility_level FROM sys.databases WHERE name = 'your_db_name';
If the result is 120 or lower, you'll need to update your compatibility level to 130, by running:
ALTER DATABASE your_db_name SET COMPATIBILITY_LEVEL = 130;
Note: In case your database is actually Azure SQL DB, you should check the version as well, as OPEN JSON is not available for versions prior to 12.x
In SQL Server Management Studio I can run this query:
select a.foo, colX, colY, colZ from tblA a
join tblB b
on (a.foo = b.foo)
Running the same query through pyodbc in python script, I get:
pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC SQL Server Driver][
SQL Server]"b" is not a recognized table hints option. If it is intended as a p
arameter to a table-valued function or to the CHANGETABLE function, ensure that
your database compatibility mode is set to 90. (321) (SQLExecDirectW)')
Can anyone explain why this query works directly against SQL Server but there seems to be a problem with the table alias when using pyodbc?
This is what I've been able to find out:
SQL Server running on Microsoft Windows NT 6.1 (7601)
SQL Server version is 11.0.5532.0
pyodbc library: pyodbc-3.0.7.win32-py2.7
1) I do not know how to produce a reproducible example and I'm not a DBA; I can just about get by in SQL. 2) I cannot create tables on this database. However: I can do the full query with 3 joins / 3 aliases works fine using the RODBC r package and the sqlQuery() call against the same db. Therefore the culprit is pyodbc so I will try to find a python dev to try reproduce and post back the findings.
UPDATE + FIX
The issue is caused by concatenation errors:
Got python developer help to find and print raw sql before it was executed in python:
select a.foo, colX, colY, colZ from tblA a join tblB bon (a.foo = b.foo)
...and similar issue at each join, caused by missing whitespace within the sql string:
sql = "select a.foo, colX, colY, colZ from tblA a "
sql += "join tblB" #no whitespace at end of string
sql += "on (a.foo = b.foo)" #runs into next segment.
Worked in r with RODBC because string in r built like:
sql = "
...full query...
"
...with no opportunity for concatenation errors.