sql >> Base de Datos >  >> RDS >> Sqlserver

Corregir el escape de identificadores delimitados en SQL Server sin usar QUOTENAME

Su QuoteName La función necesita verificar la longitud, porque la función T-SQL QUOTENAME especifica la longitud máxima que devuelve. Usando tu ejemplo:

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

Si QuoteName(identifier) tiene más de 258 caracteres, se truncará silenciosamente cuando se asigne a @delimitedIdentifier . Cuando eso sucede, abre la posibilidad de @delimitedIdentifier ser escapado indebidamente.

Hay una Artículo de MSDN por Bala Neerumalla, un "desarrollador de software de seguridad en Microsoft", que explica el tema con más profundidad. El artículo también contiene lo más parecido que he encontrado a la "documentación definitiva sobre cómo escapar de los identificadores entrecomillados en SQL Server":

Este es el código C# que estoy usando actualmente:

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