Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Corriger l'échappement des identifiants délimités dans SQL Server sans utiliser QUOTENAME

Votre QuoteName La fonction doit vérifier la longueur, car la fonction T-SQL QUOTENAME spécifie la longueur maximale qu'elle renvoie. En utilisant votre exemple :

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

Si QuoteName(identifier) est plus long que 258 caractères, il sera tronqué silencieusement lorsqu'il est attribué à @delimitedIdentifier . Lorsque cela se produit, vous ouvrez la possibilité pour @delimitedIdentifier être échappé de manière incorrecte.

Il existe un Article MSDN par Bala Neerumalla, un "développeur de logiciels de sécurité chez Microsoft", qui explique le sujet plus en profondeur. L'article contient également ce que j'ai trouvé de plus proche de la "documentation définitive sur la façon d'échapper aux identificateurs entre guillemets dans SQL Server":

Voici le code C# que j'utilise actuellement :

/// <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 ]");
    }
}