Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Kann ich von .NET die vollständige SQL-Zeichenfolge abrufen, die von einem SqlCommand-Objekt (mit SQL-Parametern) generiert wurde?

Eine einfache Schleife, die alle Parameternamen durch ihre Werte ersetzt, wird Ihnen etwas Ähnliches wie das Endergebnis liefern, aber es gibt mehrere Probleme.

  1. Da die SQL nie wirklich mit den Parameterwerten neu erstellt wird, müssen Dinge wie Zeilenumbrüche und Anführungszeichen nicht berücksichtigt werden
  2. Parameternamen in Kommentaren werden nie wirklich für ihren Wert verarbeitet, sondern unverändert gelassen

Mit diesen und unter Berücksichtigung von Parameternamen, die mit denselben Zeichen beginnen, wie @NAME und @NAME_FULL , können wir alle Parameternamen durch den Wert ersetzen, der an der Stelle dieses Parameters stehen würde:

string query = cmd.CommandText;
foreach (SqlParameter p in cmd.Parameters.OrderByDescending(p => p.ParameterName.Length))
{
    query = query.Replace(p.ParameterName, p.Value.ToString());
}

Es bleibt jedoch ein Problem dabei, und das ist, wenn ein Parameter ein String ist, dann sieht die SQL zunächst so aus:

SELECT * FROM yourtable WHERE table_code = @CODE

sieht so aus:

SELECT * FROM yourtable WHERE table_code = SOME CODE WITH SPACES

Dies ist eindeutig kein legales SQL, daher müssen wir auch einige Parametertypen berücksichtigen:

DbType[] quotedParameterTypes = new DbType[] {
    DbType.AnsiString, DbType.Date,
    DbType.DateTime, DbType.Guid, DbType.String,
    DbType.AnsiStringFixedLength, DbType.StringFixedLength
};
string query = cmd.CommandText;

var arrParams = new SqlParameter[cmd.Parameters.Count];
cmd.Parameters.CopyTo(arrParams, 0);

foreach (SqlParameter p in arrParams.OrderByDescending(p => p.ParameterName.Length))
{
    string value = p.Value.ToString();
    if (quotedParameterTypes.Contains(p.DbType))
        value = "'" + value + "'";
    query = query.Replace(p.ParameterName, value);
}