我有以下代码:

Using cmd As SqlCommand = Connection.CreateCommand
    cmd.CommandText = "UPDATE someTable SET Value = @Value"
    cmd.CommandText &= " WHERE Id = @Id"
    cmd.Parameters.AddWithValue("@Id", 1234)
    cmd.Parameters.AddWithValue("@Value", "myValue")
    cmd.ExecuteNonQuery
End Using

我想知道是否有任何方法来获得最终的SQL语句作为字符串,它应该看起来像这样:

UPDATE someTable SET Value = "myValue" WHERE Id = 1234

如果有人想知道我为什么要这么做

用于记录(失败的)语句 可以将其复制粘贴到企业管理器中进行测试


当前回答

这个方法现在对我很有效。也许它对某人有用。请原谅所有的冗余。

    Public Shared Function SqlString(ByVal cmd As SqlCommand) As String
    Dim sbRetVal As New System.Text.StringBuilder()
    For Each item As SqlParameter In cmd.Parameters
        Select Case item.DbType
            Case DbType.String
                sbRetVal.AppendFormat("DECLARE {0} AS VARCHAR(255)", item.ParameterName)
                sbRetVal.AppendLine()
                sbRetVal.AppendFormat("SET {0} = '{1}'", item.ParameterName, item.Value)
                sbRetVal.AppendLine()

            Case DbType.DateTime
                sbRetVal.AppendFormat("DECLARE {0} AS DATETIME", item.ParameterName)
                sbRetVal.AppendLine()
                sbRetVal.AppendFormat("SET {0} = '{1}'", item.ParameterName, item.Value)
                sbRetVal.AppendLine()

            Case DbType.Guid
                sbRetVal.AppendFormat("DECLARE {0} AS UNIQUEIDENTIFIER", item.ParameterName)
                sbRetVal.AppendLine()
                sbRetVal.AppendFormat("SET {0} = '{1}'", item.ParameterName, item.Value)
                sbRetVal.AppendLine()

            Case DbType.Int32
                sbRetVal.AppendFormat("DECLARE {0} AS int", item.ParameterName)
                sbRetVal.AppendLine()
                sbRetVal.AppendFormat("SET {0} = {1}", item.ParameterName, item.Value)
                sbRetVal.AppendLine()

            Case Else
                Stop

        End Select
    Next

    sbRetVal.AppendLine("")
    sbRetVal.AppendLine(cmd.CommandText)

    Return sbRetVal.ToString()
End Function

其他回答

我也有这个问题,一些参数化查询或sp的会给我一个SqlException(主要是字符串或二进制数据将被截断),并且语句很难调试(据我所知,目前没有SQL分析器支持SQL Azure)

我在这里看到了很多类似的代码。我最终把我的解决方案放在一个Sql-Library项目中,以备将来使用。

生成器可以在这里使用: https://github.com/jeroenpot/SqlHelper/blob/master/Source/Mirabeau.MsSql.Library/SqlGenerator.cs

它支持两种CommandType。文本和命令类型。StoredProcedure

如果你安装了nuget-package,你可以用下面的语句生成它:

SqlDebugHelper.CreateExecutableSqlStatement(sql, parameters);

不能,因为它不会生成任何SQL。

参数化的查询(CommandText中的那个)作为准备好的语句被发送到SQL Server。执行命令时,参数和查询文本是分开处理的。在任何时间点都不会生成完整的SQL字符串。

您可以使用SQL Profiler来查看幕后操作。

这个方法是我自己写的。我用了布鲁诺·拉尼克的代码。也许它对某人有用。

 public static string getQueryFromCommand(SqlCommand cmd)
    {
        StringBuilder CommandTxt = new StringBuilder();
        CommandTxt.Append("DECLARE ");
        List<string> paramlst = new List<string>();
        foreach (SqlParameter parms in cmd.Parameters)
        {
            paramlst.Add(parms.ParameterName);
            CommandTxt.Append(parms.ParameterName + " AS ");
            CommandTxt.Append(parms.SqlDbType.ToString());
            CommandTxt.Append(",");
        }

        if (CommandTxt.ToString().Substring(CommandTxt.Length-1, 1) == ",")
            CommandTxt.Remove(CommandTxt.Length-1, 1);
        CommandTxt.AppendLine();
        int rownr = 0;
        foreach (SqlParameter parms in cmd.Parameters)
        {
            string val = String.Empty;
            if (parms.DbType.Equals(DbType.String) || parms.DbType.Equals(DbType.DateTime))
                val = "'" + Convert.ToString(parms.Value).Replace(@"\", @"\\").Replace("'", @"\'") + "'";
            if (parms.DbType.Equals(DbType.Int16) || parms.DbType.Equals(DbType.Int32) || parms.DbType.Equals(DbType.Int64) || parms.DbType.Equals(DbType.Decimal) || parms.DbType.Equals(DbType.Double))
                val = Convert.ToString(parms.Value);

            CommandTxt.AppendLine();
            CommandTxt.Append("SET " + paramlst[rownr].ToString() + " = " + val.ToString());
            rownr += 1;
        }
        CommandTxt.AppendLine();
        CommandTxt.AppendLine();
        CommandTxt.Append(cmd.CommandText);
        return CommandTxt.ToString();
    }

如果你正在使用SQL Server,你可以使用SQL Server Profiler(如果你有的话)来查看实际执行的命令字符串。这对于复制/粘贴测试很有用,但对于日志记录恐怕就没用了。

为了记录日志,恐怕没有更好的方法了,只能自己构造字符串:

string query = cmd.CommandText;

foreach (SqlParameter p in cmd.Parameters)
{
    query = query.Replace(p.ParameterName, p.Value.ToString());
}