Is it possible for a SQL CLR User-Defined Function to return the data type varbinary(MAX)?
In the documentation it mentions:
"The input parameters and the type returned from a scalar-valued function can be any of the scalar data types supported by SQL Server, except rowversion, text, ntext, image, timestamp, table, or cursor." - they don't mention varbinary, but I'm not sure...
I have some byte-array data from the .NET side that I need to return to SQL Server from the CLR, and I'm trying to avoid having to do it with an output parameter from a stored procedure (this is how I have it working in test now).
Thanks!
Technically there is no 8000 byte maximum in the interface from SQL Server to CLR code. It is mainly a difference of how the T-SQL wrapper Stored Proc or Function is defined. Meaning, if the T-SQL Proc or Function that calls the CLR code defines the
RETURNS
asVARBINARY(MAX)
, then it shall beVARBINARY(MAX)
, whether or not you specifiedSqlBytes
orSqlBinary
as the return type of the CLR code.Both
SqlBytes
andSqlBinary
can handle the 2 GB limit, BUT the difference is in how the CLR code accepts the data.SqlBinary
(just likeSqlString
) takes the parameter value all at once whileSqlBytes
(just likeSqlChars
) provides a streaming interface so it might be more efficient for very large values.Going back to the issue that you are seeing with the pre-defined SQL Function wrapper, that
iswas a matter of how Visual Studio (technically SSDT) auto-generatesd the T-SQL. The default forSqlBinary
iswasVARBINARY(8000)
while the default forSqlBytes
iswasVARBINARY(MAX)
. In the same manner, the default forSqlString
iswasNVARCHAR(4000)
while the default forSqlChars
iswasNVARCHAR(MAX)
. Those were the defaults when this question was asked. Starting in perhaps Visual Studio 2012, the default was changed to useMAX
for all 4 of these datatypes. This is not necessarily a good thing since there is a definite performance hit for using theMAX
types vs the non-MAX
types. So, if you don't need more than 8000 bytes ofVARBINARY
or 4000 bytes ofNVARCHAR
, then you will want to override the default using one of the following methods:You can
ALTER
the Function or Proc definition after it is generated by Visual Studio, and in this case you can even change the datatypes (of either input parameters or return values) to be any size such asVARBINARY(100)
orNVARCHAR(50)
.You can use the
SqlFacet
decorator to tell Visual Studio / SSDT to auto-generate the Function or Proc definitions with the size option that you prefer as opposed to the default. The following example shows specifying the size for both input parameters and the return value (note that-1
=MAX
):Using either of these two methods you can make either
SqlBinary
orSqlBytes
map to eitherVARBINARY(1 - 8000)
orVARBINARY(MAX)
. Likewise, you can make eitherSqlString
orSqlChars
map to eithertNVARCHAR(1 - 4000)
orNVARCHAR(MAX)
.It appears that the answer is yes - you can use both varbinary(MAX) by returning "SqlBinary" or you can use SqlBytes as recommended above.
If you define it as returning a SqlBytes data type, this should correctly map to
varbinary(MAX)
in SQL Server.Whilst you can also use the SqlBinary data type, if you deploy via Visual Studio, it will be mapped onto
varbinary(8000)
rather thanvarbinary(MAX)
.