Unable to Create Multiple User Defined Functions in SQL Server Using System.Data.SqlClient

岁酱吖の 提交于 2020-04-30 08:33:14

问题


I am trying to create multiple user defined functions from within the same .sql file. I am using SQL Server and am executing my queries using the SqlClient from C#'s System.Data.

Contents of the .sql file:

CREATE FUNCTION [dbo].[GetUserId] (@username VARCHAR(32))
RETURNS INT
AS
BEGIN
    DECLARE @userId INT = -1

    SET @userId = (SELECT DISTINCT UserId FROM Users WHERE UserName = @username)

    RETURN @userId
END
GO

CREATE FUNCTION [dbo].[GetUserId2] (@username2 VARCHAR(32))
RETURNS INT
AS
BEGIN
    DECLARE @userId2 INT = -1

    SET @userId2 = (SELECT DISTINCT UserId FROM Users WHERE UserName = @username2)

    RETURN @userId2
END

Here's the error that is thrown when I execute the statement:

System.Data.SqlClient.SqlException: 'Incorrect syntax near 'GO'.
Must declare the scalar variable "@username2".
Incorrect syntax near 'END'.'

Any ideas? I'm new to SQL in general but this seems to be a lack of understanding syntax/batching to me.

EDIT: It has come to my attention that 'GO' is part of SQL Server Management Studio, and not the SqlClient. If I remove the 'GO' from my .sql file, then I get this error:

'CREATE FUNCTION' must be the first statement in a query batch.

How do I separate CREATE FUNCTION statements without using 'GO'?


回答1:


You cannot run multiple batches in a single statement.

I would suggest you to split your TSQL statement using GO and then execute the batches one by one.

string multipleUDFs = "CREATE FUNCTION... " +
"GO" + 
"CREATE FUNCTION ";
List<string> statementsToExecute = multileUDFs.Split("GO").ToList();

// Create the command 
var command = new SqlCommand(myConnection);

foreach(string sqlcommand in statementsToExecute)
{

// Change the SQL Command and execute
command.CommandText = sqlcommand;
command.ExecuteNonQuery();
}



回答2:


Below is an example using the Server Management Objects (SMO) API with the latest preview NuGet package. Unlike SqlClient, SMO can run scripts with GO batch terminators, similarly to SSMS and SQLCMD.

using System.IO;
using System.Data.SqlClient;
//reference latest NuGet preview package https://www.nuget.org/packages/Microsoft.SqlServer.SqlManagementObjects/160.1911221.0-preview#
using Microsoft.SqlServer.Management.Common;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var connection = new SqlConnection("Data Source=.;Integrated Security=SSPI"))
            {
                var serverConnection = new ServerConnection(connection);
                connection.Open();
                var sqlScript = File.ReadAllText(@"C:\temp\ScriptWithGoBatchTerminators.sql");
                serverConnection.ExecuteNonQuery(sqlScript);
            }
        }
    }
}



回答3:


In addition to Dan Guzman's answer using SMO, you can also split your SQL script text into separate SQL batches and execute each one in turn on the same connection. That is all that SSMS and SMO do anyway:

    /// <summary>
    /// Executes a script-like SQL string, using GOs to break it into
    /// seperate batches within the same session
    /// </summary>
    public void ExecSqlScript(string sqlScript, SqlConnection conn)
    {
        // change all line-breaks to LF
        string script = sqlScript.Replace("\r\n", "\n").Replace("\r", "\n");

        // split the script into separate batches using "GO"
        string[] batches = script.Split(new[] { "\nGO\n", "\ngO\n", "\nGo\n", "\ngo\n" }, StringSplitOptions.RemoveEmptyEntries);

        // execute each batch on the same connection/session
        foreach(string batch in batches)
        {
            SqlCommand cmd = new SqlCommand(batch, conn);
            cmd.ExecuteNonQuery();
        }
    }

Note: Untested



来源:https://stackoverflow.com/questions/60806335/unable-to-create-multiple-user-defined-functions-in-sql-server-using-system-data

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