CREATE PROCEDURE gets “Msg 6567, Level 16, State 2” for SQLCLR stored procedure

ⅰ亾dé卋堺 提交于 2019-12-10 18:24:48

问题


I have an issue getting SQL Server to create the stored procedure for my CLR function.

This is the error I get:

Msg 6567, Level 16, State 2, Procedure PerfInsert, Line 12 [Batch Start Line 0]
CREATE PROCEDURE failed because a CLR Procedure may only be defined on CLR methods that return either SqlInt32, System.Int32, System.Nullable, void.

What am I doing wrong?

(Updated) C# code:

using Microsoft.SqlServer.Server;
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Diagnostics;

    namespace MiddleMan
{
    public static class MiddleMan
    {
        [SqlProcedure(Name = "PerfInsert")]
        public static SqlInt32 CreateCommand(SqlChars tblString, SqlChars featureName, SqlChars connectionString, SqlChars perfionConnectionString, SqlChars logFile)
        {
            Process compiler = new Process();
            compiler.StartInfo.FileName = "C:\\SQL Server C# Functions\\PerfionLoader\\PerfionLoader\\bin\\Release\\PerfionLoader.exe";
            compiler.StartInfo.Arguments = tblString.Value + " " + featureName.Value + " " + connectionString.Value + " " + perfionConnectionString.Value + " " + logFile.Value;
            //compiler.StartInfo.UseShellExecute = false;
            //compiler.StartInfo.RedirectStandardOutput = true;
            compiler.Start();
            return SqlInt32.Zero;
        }
    }
}

(Updated) SQL code:

CREATE PROCEDURE PerfInsert
    (
        @tblString nvarchar(max)
        , @featureName nvarchar(max)
        , @connectionString nvarchar(max)
        , @perfionConnectionString nvarchar(max)
        , @logFiel nvarchar(max)
    )
    AS EXTERNAL NAME PerfInsert.[MiddleMan.MiddleMan].[CreateCommand]
GO

回答1:


You should decorate the method with:

[SqlProcedure()]
public static SqlInt32 ...
{
  ...
}

And, SQLCLR doesn't work with VARCHAR. You will need to change the T-SQL definition to use NVARCHAR(4000). If 4000 isn't enough then you can use MAX, but if input is guaranteed to be no more than 4000 bytes, then 1 - 4000 is more efficient. Might not make a difference here, but good habit to have :-).

Also, is best if you use Sql* types for the input parameters. Meaning, use SqlString and get the value from param.Value.

Related Posts:

  1. System.Web in SQL Server CLR Function (on DBA.StackExchange)
  2. System.Security.SecurityException with CLR Function

 

UPDATE

O.P. confirmed:

it turns out the issue was I needed to drop the assembly and recreate it. Didn't realize the build version was different.

Meaning, the originally stated error message of "CREATE PROCEDURE failed because a CLR Procedure may only be defined on CLR methods that return either SqlInt32, System.Int32, System.Nullable, void." was likely due to an issue that was already resolved in the code itself by the time the question was posted. That error is not the result of a missing SqlProcedure attribute, nor due to specifying VARCHAR as a datatype, so it must be due to something that we never saw.




回答2:


You don't need the SqlProcedureAttribute. That's just metadata to tell SSDT to emit the CREATE PROCEDURE. The stored procedure should use NVARCHAR(MAX) to match System.String. EG:

Compile that C# file into a .dll:

c:\test> C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc /target:library .\proc.cs

then:

create assembly PerfInsert from 'c:\test\proc.dll'
WITH PERMISSION_SET = UNSAFE;  
go
CREATE PROCEDURE PerfInsert
    (@tblString NVARCHAR(max),
     @featureName NVARCHAR(max),
     @connectionString NVARCHAR(max),
     @perfionConnectionString NVARCHAR(max),
     @logFiel NVARCHAR(max)
    )
AS EXTERNAL NAME PerfInsert.[MiddleMan.MiddleMan].[CreateCommand]
GO


来源:https://stackoverflow.com/questions/58615223/create-procedure-gets-msg-6567-level-16-state-2-for-sqlclr-stored-procedure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!