Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

A partir do .NET posso obter a string SQL completa gerada por um objeto SqlCommand (com parâmetros SQL)?


Um loop simples substituindo todos os nomes de parâmetros por seus valores fornecerá algo semelhante ao resultado final, mas existem vários problemas.
  1. Como o SQL nunca é reconstruído usando os valores dos parâmetros, coisas como novas linhas e aspas não precisam ser consideradas
  2. Os nomes dos parâmetros nos comentários nunca são realmente processados ​​por seu valor, mas deixados como estão

Com isso em vigor e levando em consideração nomes de parâmetros que começam com os mesmos caracteres, como @NAME e @NAME_FULL , podemos substituir todos os nomes de parâmetros pelo valor que estaria no lugar desse parâmetro:
string query = cmd.CommandText;
foreach (SqlParameter p in cmd.Parameters.OrderByDescending(p => p.ParameterName.Length))
{
    query = query.Replace(p.ParameterName, p.Value.ToString());
}

há um problema com isso, no entanto, e é se um parâmetro for uma string, então o SQL que inicialmente se parece com isso:
SELECT * FROM yourtable WHERE table_code = @CODE

ficará assim:
SELECT * FROM yourtable WHERE table_code = SOME CODE WITH SPACES

Isso claramente não é SQL legal, então precisamos levar em conta alguns tipos de parâmetro também:
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);
}