标签: sqlclr

如何在MS-SQL中更新程序集及其相关程序集?

情况就是这样:

我有一个Trigger.dll和一个Trigger.XmlSerializer.dll.

我使用CREATE ASSEMBLY在MSSQL中注册它们.

现在,我已经编译了两者的新版本.

我想使用ALTER ASSEMBLY来更新它们,但是你一次只能更新一个.如果您尝试更新具有依赖关系的那个,它会抱怨.这样做的诀窍是什么?

我不想丢弃并重新创建,因为我必须删除所有触发器等,并且有数据库停机时间.

sql-server sqlclr

12
推荐指数
1
解决办法
7629
查看次数

SQL Server 2008和HashBytes

我有一个很大的nvarchar我希望传递给HashBytes函数.我收到错误:

"字符串或二进制文件将被截断.无法将值NULL插入列'colname',tbale'table';列不允许空值.UPDATE失败.语句已终止."

由于资源丰富,我发现这是由于HashBytes函数的最大限制为8000字节.进一步搜索向我展示了一个"解决方案",我的大型varchar将被分开并单独进行散列,然后再与此用户定义的函数结合使用:

function [dbo].[udfLargeHashTable] (@algorithm nvarchar(4), @InputDataString varchar(MAX))
RETURNS varbinary(MAX)
AS
BEGIN
DECLARE
    @Index int,
    @InputDataLength int,
    @ReturnSum varbinary(max),
    @InputData varbinary(max)

SET @ReturnSum = 0
SET @Index = 1
SET @InputData = convert(binary,@InputDataString)
SET @InputDataLength = DATALENGTH(@InputData)

WHILE @Index <= @InputDataLength
BEGIN
    SET @ReturnSum = @ReturnSum + HASHBYTES(@algorithm, SUBSTRING(@InputData, @Index, 8000))
    SET @Index = @Index + 8000
END
RETURN @ReturnSum
END
Run Code Online (Sandbox Code Playgroud)

我打电话给:

set @ReportDefinitionHash=convert(int,dbo.[udfLargeHashTable]('SHA1',@ReportDefinitionForLookup))
Run Code Online (Sandbox Code Playgroud)

其中@ReportDefinitionHash是int,而@ReportDefinitionForLookup是varchar

传递像'test'这样的简单char会产生与我的UDF不同的int,而不是对HashBytes的正常调用.

关于这个问题的任何建议?

hash sqlclr user-defined-functions sql-server-2008

12
推荐指数
3
解决办法
1万
查看次数

Visual Studio 2010中SQLCLR项目中的计算列

在处理VS 2010 SQL CLR项目和计算列时,MS似乎有一个错误.我正在使用Pre/PostDeployScript.sql来删除/添加计算列.但是,如果我尝试从VS2010部署它,我会遇到依赖性错误.同一项目在Vs2008中100%运行.我想知道我在部署解决问题方面的选择是什么?我也与MS有联系,但他们还没有找到解决方法/解决方案.

deployment sqlclr calculated-columns visual-studio-2010

11
推荐指数
1
解决办法
361
查看次数

尽管DataAccessKind.Read存在,但SqlFunction无法打开上下文连接

我有一个非常简单的测试表值函数上SqlServer的项目: -

[SqlFunction(TableDefinition = "forename nvarchar(50)", FillRowMethodName = "TestFillRow", DataAccess = DataAccessKind.Read)]
public static IEnumerable TestConn(int ID)
{
    using (SqlConnection con = new SqlConnection("context connection=true"))
    {
        //con.Open();
        yield return "Anthony";
    }
}

public static void TestFillRow(object obj, out string forename)
{
    forename = (string)obj;
}
Run Code Online (Sandbox Code Playgroud)

请注意,连接上的"打开"当前已注释掉.部署后,我可以在SQL中执行如下操作: -

SELECT * FROM [dbo].[TestConn](1)
Run Code Online (Sandbox Code Playgroud)

一切正常.

现在我取消注释con.open(),它失败了: -

在此上下文中不允许数据访问.上下文是未使用DataAccessKind.Read或SystemDataAccessKind.Read标记的函数或方法,是从表值函数的FillRow方法获取数据的回调,或者是UDT验证方法.

我没有看到问题是什么,TestConn函数已经有了DataAccessKind.Read.

有人知道任何其他原因导致此错误?

.net c# sql-server sqlclr user-defined-functions

10
推荐指数
1
解决办法
9080
查看次数

将表作为参数传递给SQLCLR TV-UDF

我们有一个第三方DLL可以在DataTable上运行源信息并生成一些有用的值,我们试图通过SQLCLR将它连接起来,以便在SQL Server 2008中作为表值UDF进行调用.

将这个概念放在这里,我想编写一个CLR表值函数,它对来自DB的源数据表进行操作.

我很确定我理解在T-SQL方面需要发生什么; 但是,方法签名在.NET(C#)代码中应该是什么样的?"来自SQL Server的表数据?"的参数数据类型是什么?

例如

/* Setup */
CREATE TYPE InTableType 
AS TABLE (LocationName VARCHAR(50), Lat FLOAT, Lon FLOAT)
GO 

CREATE TYPE OutTableType 
AS TABLE (LocationName VARCHAR(50), NeighborName VARCHAR(50), Distance FLOAT)
GO

CREATE ASSEMBLY myCLRAssembly 
FROM 'D:\assemblies\myCLR_UDFs.dll' 
WITH PERMISSION_SET = EXTERNAL_ACCESS
GO
CREATE FUNCTION GetDistances(@locations InTableType)
RETURNS OutTableType
AS 
EXTERNAL NAME myCLRAssembly.GeoDistance.SQLCLRInitMethod
GO

/* Execution */

DECLARE @myTable InTableType
INSERT INTO @myTable(LocationName, Lat, Lon) VALUES('aaa', -50.0, -20.0)
INSERT INTO …
Run Code Online (Sandbox Code Playgroud)

c# sqlclr user-defined-functions sql-server-2008

10
推荐指数
1
解决办法
1万
查看次数

CLR表如何重视"流媒体"功能?

表值Sql Clr函数上MSDN Docs指出:

Transact-SQL表值函数将调用函数的结果实现为中间表....相反,CLR表值函数表示流式替代.不要求在单个表中实现整个结果集.托管函数返回的IEnumerable对象由调用表值函数的查询的执行计划直接调用,结果以增量方式使用....如果返回的行数非常多,它也是一个更好的选择,因为它们不必在整个内存中实现.

然后我发现"填充行"方法中不允许任何数据访问.这意味着您仍然必须在init方法中执行所有数据访问并将其保留在内存中,等待调用"填充行".我误解了什么吗?如果我不将结果强制转换为数组或列表,则会出现错误:'ExecuteReader需要一个开放且可用的连接.连接的当前状态已关闭.

代码示例:

[<SqlFunction(DataAccess = DataAccessKind.Read, FillRowMethodName = "Example8Row")>]
static member InitExample8() : System.Collections.IEnumerable = 
   let c = cn() // opens a context connection
   // I'd like to avoid forcing enumeration here:
   let data = getData c |> Array.ofSeq
   data :> System.Collections.IEnumerable

static member Example8Row ((obj : Object),(ssn: SqlChars byref)) = 
   do ssn <- new SqlChars(new SqlString(obj :?> string))
   ()
Run Code Online (Sandbox Code Playgroud)

我在这里处理几百万行.有没有办法懒惰地这样做?

sql-server f# sqlclr

10
推荐指数
1
解决办法
4894
查看次数

使用sql_variant有什么陷阱?

我已多次阅读和听到sql_variant应该避免的事情.我想我有一个很好的用例.我varchar(max)过去曾用过在同一列中存储不同的类型,但是当内置类型完全符合我的要求时,避免de/serialization开销似乎是明智的.

那么,使用的缺陷到底什么sql_variant?它们是性能相关的,还是易于编程的错误,还是其他什么?顺便说一下,如果需要考虑的话,我将从客户端代码和CLR函数中与此列进行交互.

t-sql sql-server sql-server-2005 sqlclr variant

10
推荐指数
2
解决办法
1134
查看次数

SSDT SQL Server调试不会命中CLR断点

我将SQL Server数据工具补丁应用于Visual Studio 2012(Premium)并在C#中创建了SQL Server CLR用户定义的函数项目:

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlInt32 Add42(SqlInt32 in_param)
    {
        SqlInt32 retval = in_param + 42;  // Set break point here.
        return retval;
    }
}
Run Code Online (Sandbox Code Playgroud)

在SQL Server对象资源管理器窗格中,我右键单击新发布的UDF并选择"执行函数..."我被提示提供示例输入值,然后Visual Studio将该函数(再次)发布到我的本地2012 SQL Server并生成如下所示的脚本:

DECLARE    @return_value Int

EXEC    @return_value = [dbo].[Add42] @in_param = 5

SELECT    @return_value as 'Return Value'

GO
Run Code Online (Sandbox Code Playgroud)

...并执行它,返回47的预期结果.

如果我现在在我的CLR UDF C#代码中的可执行行上放置一个断点,右键单击SQL Server对象资源管理器中的UDF函数,这次选择"调试函数...",我在生成的调试器中登陆SQL测试脚本.我可以将SQL语句单步执行到脚本的末尾,这会返回正确的结果,但是C#代码中的断点永远不会在C#调试器中到达.

该功能的术语似乎具有误导性.对于任何程序员来说,"调试"一个函数意味着逐步执行函数本身的代码中的可执行行.只需生成一个调用我的编译函数并获取结果的SQL测试工具,就是"测试"该函数.最多只有"调试"的是工具生成的测试本身,因为你不能"进入"CLR代码.唯一的选择是"跳过"它.

那么如何让Visual Studio实际调试,并在我的UDF C#代码中点击断点?

c# sqlclr user-defined-functions visual-studio-2012 sql-server-data-tools

10
推荐指数
2
解决办法
3458
查看次数

CLR具有数组参数的表值函数

我有一个像这样的SQL CLR函数:

public partial class UserDefinedFunctions {
    [Microsoft.SqlServer.Server.SqlFunction(TableDefinition = "number int", FillRowMethodName = "FillRow")]
    public static IEnumerable MyClrFunction(object obj) {
        // read obj array input and then
        var result = new ArrayList();
        result.Add((SqlInt32)1);
        result.Add((SqlInt32)2);
        result.Add((SqlInt32)3);
        return result;
    }

    public static void FillRow(object obj, out SqlInt32 number) {
        number = (SqlInt32)obj;
    }

}
Run Code Online (Sandbox Code Playgroud)

我想用这种方式使用它:

DECLARE @x arrayOfInt

INSERT INTO @x VALUES (10)
INSERT INTO @x VALUES (20)
INSERT INTO @x VALUES (30)

SELECT * FROM dbo.MyClrFunction(@x)
Run Code Online (Sandbox Code Playgroud)

arrayOfInt是:

CREATE TYPE [dbo].[arrayOfInt] …
Run Code Online (Sandbox Code Playgroud)

sql-server sqlclr user-defined-functions table-valued-parameters

9
推荐指数
1
解决办法
7602
查看次数

是否可以在SQL Server 2014中为.NET框架程序集创建非对称密钥?

我正在Visual Studio中开发一个SQL Server数据库项目,它实际上是一个用户定义的函数.在这个项目中,我将Json.NET作为参考(使用NuGet).

我设法通过首先打开数据库TRUSTWORTHY ON(因为我的项目是UNSAFE)然后运行它来发布(并使工作)我的程序集和UDF到我的SQL Server实例:

CREATE ASSEMBLY [System.Runtime.Serialization] 
FROM 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Runtime.Serialization.dll'
WITH PERMISSION_SET = UNSAFE;
Run Code Online (Sandbox Code Playgroud)

原来是Json.NET所依赖的程序集(如果我不这样做,我会收到错误)

与此同时,我读到了TRUSTWORTHY ON可能变得多么糟糕,我试图采用非对称键方式来避免打开它.

甚至在签署我自己的程序集之前,我知道我必须创建一个密钥, System.Runtime.Serialization因为我的项目依赖于Json.Net,而Json.Net依赖于它,但是当我运行它时,我得到了这个:

USE [master];
GO
  CREATE ASYMMETRIC KEY [SystemRuntimeSerializationKey]
    AUTHORIZATION [dbo]
    FROM EXECUTABLE FILE = 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Runtime.Serialization.dll';
GO

Msg 15468, Level 16, State 5, Line 3
An error occurred during the generation of the asymmetric key.
Run Code Online (Sandbox Code Playgroud)

这对我没什么帮助.

那么是否可以为.NET框架程序集生成这样的密钥,或者它是否存在将TRUSTWORTHY打开的其他解决方法?

.net sql-server sqlclr database-project .net-assembly

9
推荐指数
1
解决办法
1102
查看次数