Lately, I seem to be reading a lot of "bracket-slapping" code:
SET @Sql = 'ALTER INDEX [' + @IndexName + '] ON [' + @DBName + '].[' + @SchemaName + '].[' + @ObjectName + '] REORGANIZE '
This is much easier to read (and easier to type!) than using the QUOTENAME() function:
SET @Sql = 'ALTER INDEX ' + QUOTENAME(@IndexName) + ' ON ' + QUOTENAME(@DBName) + '.' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@ObjectName) + ' REORGANIZE '
BOL says that QUOTENAME() "[r]eturns a Unicode string with the delimiters added to make the input string a valid Microsoft SQL Server delimited identifier." So these two code snippets are pretty much interchangable, right?
But QUOTENAME() would be pretty lame if all it did was slap brackets around a string, wouldn't it? Fortunately (or unfortunately, if you've got a lot of "bracket-slapping" code laying around) it does more: it "escapes" embedded bracket characters. For example, let's take the table name 'Sales YTD [2009]', and try to create it.
-- Demonstrate that QUOTENAME() is safer than bracket-slapping. DECLARE @Sql NVARCHAR(4000) = '' DECLARE @TableOne sysname = 'Sales YTD [2009]' -- Expected to fail: table name has spaces, brackets. SET @Sql = 'CREATE TABLE ' + @TableOne + ' (x INT)' PRINT '(1) ' + @Sql EXEC sp_executesql @Sql PRINT ' ' -- Expected to fail: bracket-slapping doesn't handle brackets. SET @Sql = 'CREATE TABLE [' + @TableOne + '] (x INT)' PRINT '(2) ' + @Sql EXEC sp_executesql @Sql PRINT ' ' -- Expected to succeed. SET @Sql = 'CREATE TABLE ' + QUOTENAME(@TableOne) + ' (x INT) ' + CHAR(10) + ' ' + 'DROP TABLE ' + QUOTENAME(@TableOne) PRINT '(3) ' + @Sql EXEC sp_executesql @Sql PRINT ' '
The first attempt uses the name with no "decoration"; it's not a legal identifier name, and so will fail. The second attempt uses "bracket-slapping"; the brackets in the table's name will cause this to fail. The third, and correct, method uses QUOTENAME(). Running the code above results in this output:
(1) CREATE TABLE Sales YTD [2009] (x INT) Msg 102, Level 15, State 1, Line 1 Incorrect syntax near 'YTD'. (2) CREATE TABLE [Sales YTD [2009]] (x INT) Msg 105, Level 15, State 1, Line 1 Unclosed quotation mark after the character string 'Sales YTD [2009] (x INT)'. Msg 102, Level 15, State 1, Line 1 Incorrect syntax near 'Sales YTD [2009] (x INT)'. (3) CREATE TABLE [Sales YTD [2009]]] (x INT) DROP TABLE [Sales YTD [2009]]]
Moral of the story: always use QUOTENAME() - unless you enjoy bug hunts!
2 comments:
... or you could use the ANSI standard double quotes, and the MS-proprietary square brackets aren't an issue. (ensure to SET QUOTED_IDENTIFIER ON)
very confusing....
Post a Comment