Home > Software design >  pyodbc send parameter as nvarchar
pyodbc send parameter as nvarchar

Time:11-05

I have a query with multiple parameters that I need to run using pyodbc and I have an issue. This is a simplified version of the query, with only one parameter (I actually have 6)

declare @alertTypeName nvarchar(255)
set @alertTypeName = ?
SELECT TOP 1 Id FROM AlertType WHERE Name = @alertTypeName

@alertTypeName can have special characters, for example 'Boli şi Dăunători'. Naturally, if I were to run this query directly in SQL Server I would set @alertTypeName = N'Boli şi Dăunători'. The SELECT does not return anything without adding N in front of the text. My problem is, how do I send the value as parameter to the query in cursor.execute() so it will be correctly encoded?

This is python my code at the moment (simplified version):

query = textwrap.dedent(""" 
declare @alertTypeName nvarchar(255)
set @alertTypeName = ?
SELECT TOP 1 Id FROM AlertType WHERE Name = @alertTypeName
""")

[...]
alertTypeName = "Boli şi Dăunători"

[...]
    
paramValues = [syswinAlertId, code, alertTypeName, alertMessage, createdBy, modifiedBy]
cursor.execute(query, paramValues)

alertTypeName can have different values depending on some conditions, so I cannot just add it directly to the query text.

CodePudding user response:

In Python 3 all strings are Unicode, so if you pass a string as a parameter value then pyodbc will relay it to the ODBC Driver Manager (DM) in the appropriate format to be recognized as Unicode. For example, if we start a SQL Server Profiler trace and then run this code

cnxn = pyodbc.connect("DSN=mssqlLocal")
crsr = cnxn.cursor()
sql = "SELECT ? AS thing"
params = ("Boli şi Dăunători",)
result = crsr.execute(sql, params).fetchval()

we'll see that SQL Server is interpreting the parameter value as an N'string'

declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@P1 nvarchar(34)',N'SELECT @P1 AS thing',N'Boli şi Dăunători'
select @p1

Note that we do not need to mess with .setencoding() and .setdecoding(); the pyodbc defaults are the correct ones for SQL Server

CodePudding user response:

It seems my problem was actually caused by a faulty if condition in the code, and not by SQL. Thanks everyone for helping.

  • Related