-
Notifications
You must be signed in to change notification settings - Fork 562
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
Queries with Table Value Parameters (TVP) when the Type table is not in the dbo schema #595
Comments
I am able to reproduce the issue. pyodbc seems to be going through the usual motions, successfully calling
SQL Profiler shows that we're calling ...
... followed by ...
... and that's failing, probably because the |
Additional information: I'm not sure to what extent pyodbc is directly involved in creating the
does include 'myschema' as the "suggested_user_type_schema":
|
@v-makouz - Could this be an issue with ODBC Driver 17 for SQL Server? I've traced through the pyodbc code while running a query involving a TVP but I didn't see any evidence that pyodbc actually deals with the TYPE name (or schema), just that its ParameterType is |
I will look into this, a non-default schema is not really common and using TVPs with one may require more work on pyODBC to set the correct descriptor fields for the driver. |
Did you get anywhere with this? We are experiencing the same problem. |
"a non-default schema is not really common" Says who? I rarely even know what my default schema is when I connect to a database because I'm calling the procedures I need, whichever schema they may be in, and it's typical to define table types in the same schema as the procedures that use them, OR in a "utility" schema if they are more broadly useful. This is a major issue for me, and I can't imagine it isn't similar for most others using TVPs. It's enough that I'm having to look into alternatives to pyodbc. |
I am experiencing the same issue. I am using the ODBC Driver 17 for SQL Server and receiving the same invalid data type when attempting to call a Stored Procedure that uses a Table Valued Parameter in a schema other than the default. Just wanted to add my voice in agreement to the use of non-default schemas. |
@gordthompson I'm trying to look into this, but how do I create the custom schema? If possible can you give me the exact SQL you used to setup the repro? I tried this:
But when I run the repro script I get: |
Hi @v-makouz. That's the expected error message for this issue. This environment ... CREATE SCHEMA myschema
GO
-- create type
CREATE TYPE [myschema].[ListInt] AS TABLE
(
[Id] INT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
-- create stored procedure
CREATE PROCEDURE [myschema].[PyOdbcTestTvp](@tvp [myschema].ListInt READONLY)
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM @tvp
END ... plus this Python code ... table_values = [[1], [2]]
sql = "EXEC [myschema].[PyOdbcTestTvp] ?"
result = crsr.execute(sql, [table_values]).fetchall() ... produces that error message. On the other hand, this environment ... -- create type
CREATE TYPE [dbo].[dboListInt] AS TABLE
(
[Id] INT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
-- create stored procedure
CREATE PROCEDURE [dbo].[dboPyOdbcTestTvp](@tvp [dbo].dboListInt READONLY)
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM @tvp
END ... with this Python code ... table_values = [[1], [2]]
sql = "EXEC [dbo].[dboPyOdbcTestTvp] ?"
result = crsr.execute(sql, [table_values]).fetchall() ... works correctly, provided that your default schema is |
@gordthompson Ah, OK, thanks, I got a little confused by the two similar SQLs, it all makes sense now, I can repro and looking into it |
Any headway on this issue? Execute sql got error:('42000', "[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Column, parameter, or variable # 2: Cannot find data type READONLY. (2715) (SQLExecDirectW); [42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Statement(s) could not be prepared. (8180); [42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Parameter or variable '@p2' has an invalid data type. (2724)") where my second parameter is a TVP with a uniqueidentifier and float value. |
( Question from @sandeepnmenon is not relevant here. See #732 ) |
I am facing same issue. when creating type in dbo , no issues. but when in another schema. below error. Failed to execute function - PyOdbcTestTvp. Exception: [ProgrammingError] ('42000', '[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Column, parameter, or variable #1: Cannot find data type ListInt. (2715) (SQLParamData)') |
We likewise are seeing issues with using the added TVP functionality, since many of our tables do not use a default dbo schema. Any enhancements or support for this issue would be greatly appreciated! |
@v-chojas , @v-makouz – Any feedback from my comments of 2019-07-25 and 2019-08-06? It really does look like the ODBC driver is the one responsible for
the call exec sp_prepare @p1 output,N'@P1 [ListInt] READONLY',N'EXEC [myschema].[PyOdbcTestTvp] @P1',1 and the output from exec sp_describe_undeclared_parameters N'EXEC [myschema].[PyOdbcTestTvp] @P1' does tell the driver that the ("suggested") schema name is
|
I am also interested in this issue. My employer deals with a lot of databases with many different schemas. To work around this issue I've been using global temp tables, as a workaround. This bug fix would be a great benefit. |
I seem to end up on this thread every time I have to use TVPs with Microsoft SQL Server (which is anytime I have to support SQL 2012 or SQL 2014. In SQL 2016+ we don't use TVP and favor JSON as our multi-row mechanism). I am again trying to get my proc call with a TVP to quit giving me the "Cannot find data type READONLY" message. It has consistently worked to setup a user whose default schema is the same schema as the TVP. This time however it's not working so I've missed something in my user setup or something and continue to work through that. During this round of the fight though I came across an article from Microsoft and thought it could help here. (I've made it as far as buying a C class from Udemy so I'm no help in actually solving the issue so all I can do is share what I find, I hope it helps. Uses of ODBC Table-Value Paramaters
It at least appears that Microsoft intended to support ODBC and TVPs in different schemas than the user's default schema |
Try #904 That doc needs fixed, neither of those two constants are defined and the last sentence contradicts the one before it. |
Thanks @v-chojas . #904 does seem to do the trick. So the fix is to use string values to explicitly specify the name of the type and its schema as the first two elements of the TVP "value". In the example above: table_values = [(1,), (2,)] # list of tuples
sql = "EXEC [myschema].[PyOdbcTestTvp] ?"
tvp_payload = [["ListInt", "myschema", ] + table_values]
print(tvp_payload)
# [['ListInt', 'myschema', (1,), (2,)]]
# i.e., a single-element list containing a list of the form: [str, str, tuple, tuple, tuple, …]
result = crsr.execute(sql, tvp_payload).fetchall()
print(result)
# [(1, ), (2, )] TODO: Once #904 gets merged and released we should probably add an entry in the wiki. |
Environment
Issue
I'm glad to see TVPs are supported now. I was going through some testing against an Azure SQL database and it seems that the TVP type needs to be created on the
dbo
schema in order for this to work. If the TVP type is in a schema different thandbo
, I get the error[Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Column, parameter, or variable #1: Cannot find data type ListInt
Database setup
My python code
Following pyodbc
sqlservertests.py
The example works as expected if the TVP type is created in the
dbo
schema like this:Is there anything I can do to make this work with the TVP type in a schema other than
dbo
? Thanks!The text was updated successfully, but these errors were encountered: