使用C#在SQL Server上执行sql文件

发布于 2024-10-14 13:43:17 字数 202 浏览 2 评论 0原文

我有许多过程、视图、函数等文件

。我想在 SQL Server 2005/2008 上的适当数据库中执行这些文件(创建组件)。

还有一点是我想使用 C# 来执行它们。

另一点需要提及的是,我希望应用程序也可以在远程 SQL Server 上执行此文件。另外客户端机器可能没有osql、sqlcmd命令工具。

有人可以指导我吗?

I have many files for procedures, views, functions, etc.

I want to execute these files (creating components) in appropriate database on SQL Server 2005/2008.

Also the point is I want to execute them using C#.

Another point to mention, I want the application to be such that I can execute this files on a remote SQL Server too. Also client machine may not have osql,sqlcmd command tool.

Can someone please guide me on this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

厌倦 2024-10-21 13:43:17

这取决于它们是什么类型的文件。例如,如果它们包含实际的T-SQL命令(并且不是您在SSMS中运行的批处理文件,其中包含一个批处理分隔符(如 GO),那么您只需创建一个连接、一个命令,然后读取文件的内容并使用它来填充命令的 CommandText 属性。

例如:

void ExecuteFile(string connectionString, string fileName)
{
    using(SqlConnection conn = new SqlConnection(connectionString))
    {
        string data = System.IO.File.ReadAllText(fileName);

        conn.Open();

        using(SqlCommand cmd = conn.CreateCommand())
        {
            cmd.CommandText = data;
            cmd.ExecuteNonQuery();
        }
    }
}

如果它是批处理文件,您需要将文件拆分为单独的批处理并单独处理它们。最简单的方法就是使用 string.Split,但请记住,它在拆分时不会遵守 SQL 解析规则(例如,如果 GO 出现在SQL语句,它将把命令分成两批,这显然会失败)。

更一般地说,您可以通过以下方式修改代码来了解此处需要执行的操作:

string[] batches = SplitBatches(System.IO.File.ReadAllText(fileName));

conn.Open();

using(SqlCommand cmd = conn.CreateCommand())
{
    foreach(string batch in batches)
    {
        cmd.CommandText = batch;
        cmd.ExecuteNonQuery();
    }
}

名为 SplitBatches 的函数的实现由您决定。

This depends on what sort of files they are. If, for example, they only contain actual T-SQL commands (and aren't batch files that you'd run in, say, SSMS, which would contain a batch separator like GO), then you just need to create a connection, a command, then read the contents of the file and use that to populate the CommandText property of the command.

For example:

void ExecuteFile(string connectionString, string fileName)
{
    using(SqlConnection conn = new SqlConnection(connectionString))
    {
        string data = System.IO.File.ReadAllText(fileName);

        conn.Open();

        using(SqlCommand cmd = conn.CreateCommand())
        {
            cmd.CommandText = data;
            cmd.ExecuteNonQuery();
        }
    }
}

If it's a batch file, you'll need to split the file into individual batches and process those individually. The simplest method is just to use string.Split, but bear in mind that it won't respect SQL parsing rules when it splits (for example, if GO appears within a SQL statement, it's going to split the command up into two batches, which will obviously fail).

More generally, you can see what you'd need to do here by modifying the code in this way:

string[] batches = SplitBatches(System.IO.File.ReadAllText(fileName));

conn.Open();

using(SqlCommand cmd = conn.CreateCommand())
{
    foreach(string batch in batches)
    {
        cmd.CommandText = batch;
        cmd.ExecuteNonQuery();
    }
}

The implementation of a function called SplitBatches is up to you.

↘人皮目录ツ 2024-10-21 13:43:17

通常,最简单的方法是在“GO”语句上拆分脚本并单独执行每个项目。如果脚本的注释中包含 GO 语句,则此解决方案将不起作用。

private readonly Regex _sqlScriptSplitRegEx = new Regex( @"^\s*GO\s*$", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled );
public void ExecuteSqlScript( string scriptText )
{
    if ( string.IsNullOrEmpty( scriptText ) )
        return;

    var scripts = _sqlScriptSplitRegEx.Split( scriptText );
    using ( var conn = new SqlConnection( "connection string" ) )
    {
        using ( var ts = new TransactionScope( TransactionScopeOption.Required, new TimeSpan( 0, 10, 0 ) ) )
        {
            foreach ( var scriptLet in scripts )
            {
                if ( scriptLet.Trim().Length == 0 )
                    continue;

                using ( var cmd = new SqlCommand( scriptLet, conn ) )
                {
                    cmd.CommandTimeout = this.CommandTimeout;
                    cmd.CommandType = CommandType.Text;
                    cmd.ExecuteNonQuery();
                }
            }

            ts.Complete();
        }
    }
}

Typically, the simplest way is to split the script on the "GO" statement and execute each item separately. This solution will not work if the script contains a GO statement within a comment.

private readonly Regex _sqlScriptSplitRegEx = new Regex( @"^\s*GO\s*$", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled );
public void ExecuteSqlScript( string scriptText )
{
    if ( string.IsNullOrEmpty( scriptText ) )
        return;

    var scripts = _sqlScriptSplitRegEx.Split( scriptText );
    using ( var conn = new SqlConnection( "connection string" ) )
    {
        using ( var ts = new TransactionScope( TransactionScopeOption.Required, new TimeSpan( 0, 10, 0 ) ) )
        {
            foreach ( var scriptLet in scripts )
            {
                if ( scriptLet.Trim().Length == 0 )
                    continue;

                using ( var cmd = new SqlCommand( scriptLet, conn ) )
                {
                    cmd.CommandTimeout = this.CommandTimeout;
                    cmd.CommandType = CommandType.Text;
                    cmd.ExecuteNonQuery();
                }
            }

            ts.Complete();
        }
    }
}
深海不蓝 2024-10-21 13:43:17

通常,您所要做的就是使用 执行它们SqlCommand.ExecuteNonQuery,一次一批。这让您需要使用当前设置的批次分隔符(通常为 GO)将脚本拆分为批次。免费库 dbutilsqlcmd 可用于处理 SQL 脚本,因为它不仅处理分隔符,但还有 SQLCMD 扩展(:setvar:connect 等)。

Normally all you have to do is just execute them with SqlCommand.ExecuteNonQuery, one batch at a time. That leaves you the task of splitting the scripts into batches, using the currently set batch delimiter (usually GO). The free library dbutilsqlcmd can be used to handle SQL scripts, as it processes not only the delimiter, but SQLCMD extensions as well (:setvar, :connect etc).

朮生 2024-10-21 13:43:17

使用标准 ADO 会“起作用” -- SQL DDL 可以使用 SqlCommand.ExecuteNonQuery 发送,例如。

...但我建议使用数据库项目(带有远程暂存部署或 VSDBCMD)或 SQLCMD(可能与 PowerShell 脚本结合使用 :-) 或 SQL Management Studio 等工具之一。它们的设计目的是对于这类东西。

Using standard ADO would "work" -- SQL DDL can be sent using SqlCommand.ExecuteNonQuery, for instance.

...but I'd recommend using a Database Project (with a remote staging deploy or VSDBCMD) or one of the tools such as SQLCMD (perhaps in conjunction with a PowerShell script :-) or SQL Management Studio, etc. They are designed for this sort of stuff.

べ映画 2024-10-21 13:43:17

您可以使用 TextReader 读入命令,然后使用 ExecuteNonQuery 将 TextReader 结果作为命令。

You could read in the commands using a TextReader, then use ExecuteNonQuery with the TextReader results as the command.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文