SQLAlchemy Text Parameter Binding gives '?' - python

I'm using ODBC Driver 17 for SQL Server
I have this:
q = text('select top 10 * from :x')
conn.execute(q, x="mytable")
which fails returning:
sqlalchemy.exc.ProgrammingError: (pyodbc.ProgrammingError) ('42000', '[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Must declare the table variable "#P1". (1087) (SQLExecDirectW)')
[SQL: select top 10 * from ?]
[parameters: ('mytable',)]
Running q = test('select top 10 * from mytable') works however.
I'm at a lost as I've tried bindparams.

Martijin's comment is correct. The bind parameters only work for data.
q = text('select top 10 * from :x')
conn.execute(q, x="mytable")
is invalid.
But this,
q = text('select :x from mytable')
conn.execute(q, x="thing1")
works.

Related

executemany with pyodbc, stored procedures and SQL Server

I would be grateful to know what is the easiest way to diagnose this error, as it does not seem to be easy to display what SQL is being executed via pyodbc.
My stored procedure looks like this:
ALTER PROCEDURE [dbo].[s_populate_Test_sp]
#TestDateTime DATETIME,
#TestInt INT,
#TestMoney MONEY,
#TestVarChar500 VARCHAR(500),
#TestFloat FLOAT
AS
SET NOCOUNT ON
INSERT INTO [dbo].[tbl_Test_sp2] (test_datetime, test_int, test_money, test_varchar500, test_float)
VALUES (#TestDateTime, #TestInt, #TestMoney, #TestVarChar500, #TestFloat)
I can execute this stored procedure once successfully using raw text (the commented code below), but I am having difficulty with executemany:
import os
import pyodbc
import datetime
def test_sp():
# Constants
dir_path = os.path.dirname(os.path.realpath(__file__))
# Connect
server = 'xxx'
db2 = 'xxx'
conn_str = 'DRIVER={SQL Server};SERVER=' + server + \
';DATABASE=' + db2 + ';Trusted_Connection=yes'
conn=pyodbc.connect(conn_str, autocommit=False)
cursor = conn.cursor()
cursor.fast_executemany = True
for row in range(10000):
# sql = '''EXEC [dbo].[s_populate_Test_sp] #TestDateTime = '2020-01-01 13:00',
# #TestInt = 999,
# #TestMoney = '£12.34',
# #TestVarChar500 = 'Hello My Name is Jon',
# #TestFloat = 1.234567
# '''
# cursor.execute(sql)
sql = '''exec s_populate_Test_sp (#TestDateTime = ?, #TestInt = ?, #TestMoney = ?, #TestVarChar500 = ?, #TestFloat = ?)'''
values = ['2020-01-01 13:00', 999, '£12.34', 'Hello My Name is Jon', 1.234567]
cursor.executemany(sql, [values])
conn.commit()
if __name__ == '__main__':
test_sp()
Unfortunately this yields a rather cryptic error message:
ProgrammingError: ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near '#TestDateTime'. (102) (SQLExecute); [42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Statement(s) could not be prepared. (8180)")
I can't find a way of displaying the SQL before it gets executed, so it's all a bit trial and error at the moment.
Many thanks
Per the comments, the answer was to remove the parentheses, the £ sign and use a datetime.datetime object:
sql = '''exec s_populate_Test_sp #TestDateTime = ?, #TestInt = ?, #TestMoney = ?, #TestVarChar500 = ?, #TestFloat = ?'''
values = [datetime.datetime.now(), 999, 12.34, 'Hello My Name is Jon', 1.234567]
It is frustrating that it is so slow. Over my firm's VPN it can do 400 records per minute and on a virtual machine close to the server it can do 9,000 records per minute. I suspect this is one of the limitations of pyodbc and SQL Server, and I will have to do bcp or something like that for larger datasets.

Get the last select statement from a pyodbc SQL query

I am performing a long SQL query with several temp tables created along the way
conn = pyodbc.connect('Driver={SQL Server};'
'Server=Server;'
'Database=DB;'
'Trusted_Connection=yes;')
cursor = conn.cursor()
query = """
Select *
into #Cohort
From TABLE1
SELECT * from TABLE2 as tab2
inner join #Cohort as tab1 on tab2.id = tab1.id
"""
population = pd.read_sql_query(query,conn)
and getting the error
TypeError: 'NoneType' object is not iterable
From what I read it is because read_sql_query() only takes the first SELECT statement.
How do I specify what SELECT statement to return using it or another function?
Worked by adding SET NOCOUNT ON;
Thanks Gord Thompson!

create SQL table from existing table using pyodbc/turbodc in python

I would like to create a SQL table from an existing table. I'm using the turbodbc module (which is very similar to pyodbc).
# connect to database
conn = turbodbc.connect(connection_string="my_connection_string")
cursor = conn.cursor()
# execute SQL code
cursor.execute((" create table Test_Puts as"
" select * from OptionValue"
" where call_put = 'P'"))
However, I get the error message:
ODBC error
state: 42000
native error code: 156
message: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Incorrect syntax near the keyword 'select'.
Try to use this syntax:
select * into Test_Puts from OptionValue where call_put = 'P'
So, instead of this:
" create table Test_Puts as"
" select * from OptionValue"
" where call_put = 'P'"
use this:
" select * into Test_Puts"
" from OptionValue"
" where call_put = 'P'"

pyodbc not recognising parameter placeholder in multi-line string

Why is pyodbc throwing this error:
pyodbc.ProgrammingError: ('The SQL contains 0 parameter markers, but 1 parameters were supplied', 'HY000')
When I do have a parameter marker in the query?
It seems it only complains when I use a multiline string in python.
i.e. this is causing an error:
sql = """
SELECT a.r_object_id, a.object_name, a.document_status, a.document_id, a.document_status, b.r_version_label, a.r_link_cnt
from pharma_document_sp a, pharma_document_rp b where a.r_object_id = b.r_object_id and b.r_version_label = 'LATEST APPROVED' and a.document_id = ?
"""
cursor_cara.execute(sql, doc_id)
But this is OK:
sql = "SELECT a.r_object_id, a.object_name, a.document_status, a.document_id, a.document_status, b.r_version_label, a.r_link_cnt "
sql = sql + " from pharma_document_sp a, pharma_document_rp b where a.r_object_id = b.r_object_id and b.r_version_label = 'LATEST APPROVED' and a.document_id = ?"
cursor_cara.execute(sql, doc_id)
I am using:
pyodbc version 4.0.27, SQL ODBC Server Driver 17, Python 3.7.4

Can't get my SQL to display my score in my database form my pygame

I have tried to create a piece of code so when my game is over or the play wins he score is displayed in the database.
Game Code:
def gameover():
message = Msg("Game Over")
message.update()
player.kill()
shot.kill()
SQL = 'INSERT INTO TblScore(Score) VALUES (' + str(score.value)
Databaseconnector.INSERT(SQL)
Database Connection Code:
def INSERT(SQL):
print(SQL)
cursor.execute(SQL)
conn.commit()
Error:
ProgrammingError: ('42000', '[42000] [Microsoft][ODBC Microsoft Access Driver] Syntax error in INSERT INTO statement. (-3502) (SQLExecDirectW)')
You forgot the closing bracket:
SQL = 'INSERT INTO TblScore(Score) VALUES (' + str(score.value) + ')'
^^^^^^^

Categories

Resources