Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Correggere l'escape degli identificatori delimitati in SQL Server senza utilizzare QUOTENAME

Il tuo QuoteName la funzione deve controllare la lunghezza, poiché la funzione T-SQL QUOTENAME specifica la lunghezza massima che restituisce. Usando il tuo esempio:

String.Format(@"declare @delimitedIdentifier nvarchar(258);
set @delimitedIdentifier = {0};", QuoteName(identifier));

Se QuoteName(identifier) è più lungo di 258 caratteri, verrà troncato silenziosamente quando assegnato a @delimitedIdentifier . Quando ciò accade, apri la possibilità per @delimitedIdentifier sfuggire in modo improprio.

Esiste un Articolo MSDN di Bala Neerumalla, uno "sviluppatore di software di sicurezza presso Microsoft", che spiega l'argomento in modo più approfondito. L'articolo contiene anche la cosa più vicina che ho trovato alla "documentazione definitiva su come sfuggire agli identificatori tra virgolette in SQL Server":

Questo è il codice C# che sto attualmente utilizzando:

/// <summary>
/// Returns a string with the delimiters added to make the input string
/// a valid SQL Server delimited identifier. Brackets are used as the
/// delimiter. Unlike the T-SQL version, an ArgumentException is thrown
/// instead of returning a null for invalid arguments.
/// </summary>
/// <param name="name">sysname, limited to 128 characters.</param>
/// <returns>An escaped identifier, no longer than 258 characters.</returns>
public static string QuoteName(string name) { return QuoteName(name, '['); }

/// <summary>
/// Returns a string with the delimiters added to make the input string
/// a valid SQL Server delimited identifier. Unlike the T-SQL version,
/// an ArgumentException is thrown instead of returning a null for
/// invalid arguments.
/// </summary>
/// <param name="name">sysname, limited to 128 characters.</param>
/// <param name="quoteCharacter">Can be a single quotation mark ( ' ), a
/// left or right bracket ( [] ), or a double quotation mark ( " ).</param>
/// <returns>An escaped identifier, no longer than 258 characters.</returns>
public static string QuoteName(string name, char quoteCharacter) {
    name = name ?? String.Empty;
    const int sysnameLength = 128;
    if (name.Length > sysnameLength) {
        throw new ArgumentException(String.Format(
            "name is longer than {0} characters", sysnameLength));
    }
    switch (quoteCharacter) {
        case '\'':
            return String.Format("'{0}'", name.Replace("'", "''"));
        case '"':
            return String.Format("\"{0}\"", name.Replace("\"", "\"\""));
        case '[':
        case ']':
            return String.Format("[{0}]", name.Replace("]", "]]"));
        default:
            throw new ArgumentException(
                "quoteCharacter must be one of: ', \", [, or ]");
    }
}