SQL Using Variable Value - python

I have a variable like below in python;
run_id=5654
When i execute the below code;
df=curs.execute("select* from [DATABASE] where RunId=run_id")
I got an error:
DataError: ('22018', "[22018] [Microsoft][ODBC SQL Server Driver][SQL
Server]Conversion failed when converting the varchar value 'run_id' to
data type smallint. (245) (SQLExecDirectW)")
Could you please help me about this? How can i proceed?

Assuming you are connecting to your SQL Server instance using pyodbc, you should use a prepared statement with ? as the placeholder:
run_id = '5654'
df = curs.execute("SELECT * FROM [DATABASE] WHERE RunId = ?", (run_id,))

Related

Alter database query with variables using Python

I am trying to execute below SQL query by introducing 2 variables in Python but getting error,
Original Query:
ALTER DATABASE db1 MODIFY (SERVICE_OBJECTIVE = 'DW300');
I want to use variables for db1 and 'DW300'. I have tried below statement in Python and got error.
dwu = 'DW100'
sqlpool = 'db1'
cursor.execute("""ALTER DATABASE ? MODIFY (SERVICE_OBJECTIVE = ?) """, (sqlpool, dwu))
Error: pyodbc.ProgrammingError: ('42000', "[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Incorrect syntax near '#P1'. (102) (SQLExecDirectW)")
I use sqlite and it accepts this answe.
try the use of fstrings
f"""Alter Database {sqlpool} modify (service objective = {dwu}) """

SQLAlchemy Core - Subquery missing an alias

I was working on a straightforward SQLAlchemy Core (Python 3.x) count unique query using the following code:
table_object = sqlalchemy.Table(table_name, metadata, autoload=True, autoload_with=engine, schema=schema)
agg_fields = [get_column_correct_case(table_object, col) for col in agg_fields]
agg_col_obj = [table_object.c[col] for col in agg_fields]
agg_query = sqlalchemy.select(agg_col_obj).select_from(table_object)\
.group_by(*agg_fields).count()
engine.scalar(agg_query)
While I believe this should be valid SQLAlchemy Core code, its execution returned a PYODBC error:
(pyodbc.ProgrammingError) ('42000', "[42000] [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]
Incorrect syntax near ')'. (102) (SQLExecDirectW);
[42000] [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Statement(s) could not be prepared. (8180)")
The SQL query generated by this code which failed to execute properly was:
[SQL: SELECT count([ACCOUNT]) AS tbl_row_count
FROM (SELECT dbo.history.[ACCOUNT] AS [ACCOUNT], dbo.history.[RTXNNBR] AS [RTXNNBR]
FROM dbo.history
GROUP BY dbo.history.[ACCOUNT], dbo.history.[RTXNNBR])]
Running the query directly in SQL Server, it appears to be failing because the nested select is missing an alias. Is this a bug? If not, how do I fix this code?
I figured out the answer. I was surprised it was necessary, but this can be resolved by giving the query to be counted an alias.
So
agg_query = sqlalchemy.select(agg_col_obj).select_from(table_object)\
.group_by(*agg_fields).count()
becomes:
agg_query = sqlalchemy.select(agg_col_obj).select_from(table_object)\
.group_by(*agg_fields).alias('a').count()
which now works.

How to parameterize pyodbc identifiers in queries safely?

I have written a small tool which migrates data from SQL Server to Postgres.
To make things work, I did it quick and dirty using string concats since I had a lot of other issues to solve and I did not want to bother with the SQL at the time. But now that everything is sorted out, I want to do things porperly in the SQL department.
The unsafe quick and dirty version :
import pyodbc
# this is the bad example DON'T do this
def getDataFromTable(self,table):
"""
Gets all data from the specified Table.
table -- Table name as string
"""
cursor = self.cursor
SQL = f"""SELECT * FROM {table}""" ## DON'T do this
cursor.execute(SQL)
rows = cursor.fetchall()
records = []
for row in rows:
records.append(list(row))
return records
This works perfectly fine, but is a SQL injection waiting to happen.
I want to build something like this (I have omitted the unchanged parts):
...
cursor = self.cursor
SQL = f"""SELECT * FROM ?""" # Use parameters insted of string concats
cursor.execute(SQL, table) # pass parameters to the execute method.
rows = cursor.fetchall()
...
This looks nice an safe, but also does not work. Following error pops up :
pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Die #P1-Tabellenvariable muss deklariert werden. (1087) (SQLExecDirectW); [42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Anweisung(en) konnte(n) nicht vorbereitet werden. (8180)')
It's in German but roughly translates to: table variables must be declared, statement could not be prepared.
How can I pass a variable into the execute method to take the identifiers place safely?
You can not have a variable for table name in SQL Server. You can generate a string in python and then execute it.
table_name = 'table1'
query = "Select * from %s" % table_name
Or you can use Dynamic SQL.

Error while inserting values of multiple lists into columns of database (SQL Server + Python)

I have created a Dataset containing the various attributes of tweets extracted from Tweepy, the Twitter API. I am trying to insert values from various columns of that Dataset into a database created in SQL Server, by typecasting each attribute into a list. I know this is probably THE worst way to go about this, but once I have the problem solved I'll definitely be improving this code.
connection = pyodbc.connect('DRIVER={SQL Server};Server=***;Database=Tweets;User Id=***;Password=***;')
cursor = connection.cursor()
ID_list = list(dataset['ID'])
text_list = list(dataset['Text'])
fav_count_list = list(dataset['Favourite_Counter'])
retweet_count_list = list(dataset['Retweet_Counter'])
timestamp_list = list(dataset['Timestamp'])
location_list = list(dataset['Location'])
for i in range(1,len(ID_list),1):
cursor.execute('INSERT INTO Tweet(ID,Text,Favourite_Counter,Retweet_Counter,Timestamp,Location) VALUES(%?,%?,%?,%?,%?,%?)',(tweetID_list[i],text_list[i],fav_count_list[i],retweet_count_list[i],timestamp_list[i],location_list[i]))
connection.commit()
cursor.close()
connection.close()
Once I execute this code block, I get the following error:
---------------------------------------------------------------------------
ProgrammingError Traceback (most recent call last)
<ipython-input-62-a61238cf4963> in <module>()
11
12 for i in range(1,len(ID_list),1):
---> 13 cursor.execute('INSERT INTO Tweet(ID,Text,Favourite_Counter,Retweet_Counter,Timestamp,Location) VALUES(%?,%?,%?,%?,%?,%?)',(tweetID_list[i],text_list[i],fav_count_list[i],retweet_count_list[i],timestamp_list[i],location_list[i]))
14 connection.commit()
15
ProgrammingError: ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near '#P1'. (102) (SQLExecDirectW); [42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Statement(s) could not be prepared. (8180)")
I've been trying to solve this for a good part of 2 hours, with not much progress. Can anyone please help me and give me a good solution for solving this error?
You are using ODBC for connecting to the database. Timestamp is an ODBC reserved word (see here).
Try escaping it, using [Timestamp] (or change the name to something safer).

Unable to CREATE DATABASE via PyODBC connection

I am using pyodbc in python 2.7 with MS SQL Server 2008R.
Here is my code for creating a database (the SQL code which works fine in SQL alone, but crash when executed in python)
SQL_command = """
IF EXISTS(SELECT * FROM sys.databases WHERE [name] = 'NewDatabase')
DROP DATABASE NewDatabase
"""
conn.cursor.execute(SQL_command)
SQL_command = """
CREATE DATABASE NewDatabase
ON
(
NAME = 'NewDatabase_data'
, FILENAME='D:\MSSQL\DATA\NewDatabase_data.mdf'
, SIZE = 4096KB
, FILEGROWTH = 4096KB
)
LOG ON
(
NAME = 'NewDatabase_log'
, FILENAME='D:\MSSQL\LOG\NewDatabase_log.ldf'
, SIZE = 4096KB
, FILEGROWTH = 10%
)
COLLATE SQL_Latin1_General_CP1_CI_AS
"""
conn.cursor.execute(SQL_command)
SQL_command = """
ALTER DATABASE
NewDatabase
SET RECOVERY SIMPLE
"""
conn.cursor.execute(SQL_command)
However, I've got following error message:
pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC SQL
Server Driver][SQL Server]CREATE DATABASE statement not allowed within
multi-statement transaction. (226) (SQLExecDirectW)')
May I know what is wrong with my code?
Many thanks.
====================================================================================
So, after taking the advice from #Matthias, I've executed commit after the drop database, then the error message became:
pyodbc.ProgrammingError: ('42000', "[42000] [Microsoft][ODBC SQL
Server Driver][SQL Server]CREATE FILE encountered operating system
error 123(failed to retrieve text for this error. Reason: 15105) while
attempting to open or create the physical file
'D:\MSSQL\DATA\NewDatabase_data.mdf'. (5123)
(SQLExecDirectW); [42000] [Microsoft][ODBC SQL Server Driver][SQL
Server]CREATE DATABASE failed. Some file names listed could not be
created. Check related errors. (1802)")

Categories

Resources