-
Notifications
You must be signed in to change notification settings - Fork 566
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
'[HY004] [Microsoft][ODBC Driver 17 for SQL Server]Invalid SQL data type (0) (SQLBindParameter)' When first row of TVP contains None as a cell value #862
Comments
In general, Nones are a bit problematic since they don't provide any hints of the type that the parameter should be sent as; when the parameter is not a TVP, then the SQLDescribeParam function is used to determine the type, but when it is a TVP, SQLDescribeParam only says that the parameter is a TVP, and does not provide information about its individual columns. If the parameter is not None, then it can be used to determine the type, which is why it works when the first row doesn't have Nones --- pyODBC uses the contents of that row to determine what types it should bind each of the sub-parameters in the TVP as. |
Hi Chojas, I did try to take a stab at fixing it yesterday. I was able to compile the code and create a python test to replicate it but the ODBC protocol was too much to grok for me... It was my first time dabbling in the ODBC API. |
For the 2nd idea, maybe pyodbc can provide a class we can optionally use to send data to pyodbc.. E.x.: from dataclasses import dataclass
@dataclass
class TableValueParameter:
column_types: list[type] # the python type that to map the the TVP column
rows: # the sequence that we normally send to pyodbc for a TVP |
If having pyodbc auto-detect the TVP types is not feasible (as suggested by my research into a related issue indicating that all pyodbc can get from SQL Server itself is that the ParameterType is |
I give up... I tried using TVP in AWS Lambda and pyodbc caused a core dump. I'll just upload JSON strings instead of TVP. |
I have Error from this code: |
"SQL Server " is a very old driver from SQL Server 6.x, which obviously did not support TVP. |
Closing because
This fails param_array = [
[None, 0],
[1, 1],
]
cnxn = pyodbc.connect(conn_str)
crsr = cnxn.cursor()
crsr.execute("EXEC TestSelectTVP ?", [param_array]).fetchall() while this works param_json = [dict(c01=x, c02=y) for x, y in param_array]
print(param_json)
# [{'c01': None, 'c02': 0}, {'c01': 1, 'c02': 1}]
sql = """\
SET NOCOUNT ON;
DECLARE @tvp [dbo].[TVPType];
INSERT INTO @tvp
SELECT c01, c02
FROM OPENJSON(?)
WITH (
c01 int '$.c01',
c02 int '$.c02'
);
EXEC [dbo].[TestSelectTVP] @tvp;
"""
crsr.execute(sql, json.dumps(param_json, default=str))
print(crsr.fetchall())
# [(None, 0), (1, 1)] |
Please first make sure you have looked at:
Environment
To diagnose, we usually need to know the following, including version numbers. On Windows, be
sure to specify 32-bit Python or 64-bit:
Issue
The below code fails because the 1st row of param_array contains None. If you swap the rows, the error goes away.. So it seems that TVP will only work when the 1st row contains all non-None values... All other rows can contain None.
It's similar to #520
Often it is easiest to describe your issue as "expected behavior" and "observed behavior".
The text was updated successfully, but these errors were encountered: