Based on the comment by ypercubeᵀᴹ which reads:
...can you find a string x that parsename(quotename(x),1) will be different than x? If not, that falls into the definition of "inverse function" ;) ...
... I created a simple statement to have a look at the different values returned by these functions. The code is as follows:
Code
DECLARE
-- Text that I will be converting using QUOTENAME()
@Text2Quote_1 AS NVARCHAR(20),
@Text2Quote_2 AS NVARCHAR(20),
@Text2Quote_3 AS NVARCHAR(20),
@Text2Quote_4 AS NVARCHAR(20),
-- The characters used for "quotation"
@QuoteChar_1 AS NCHAR(1),
@QuoteChar_2 AS NCHAR(1),
@QuoteChar_3 AS NCHAR(1),
-- The Parsing option as defined in the original MS documnenation for PARSSENAME()
@ParseParam AS INT
SET @Text2Quote_1 = N'Test'
SET @Text2Quote_2 = N'[Test]'
SET @Text2Quote_3 = N'Test.dbo.test'
SET @Text2Quote_4 = N'[Test].[dbo].[test]'
SET @QuoteChar_1 = ''''
SET @QuoteChar_2 = '['
SET @QuoteChar_3 = '"'
SET @ParseParam = 1 -- Parsing level : Object name
-- checking the results for ' single quotes
SELECT @Text2Quote_1 AS OriginalText_1,
@Text2Quote_2 AS OriginalText_2,
@Text2Quote_3 AS OriginalText_3,
@Text2Quote_4 AS OriginalText_4
SELECT QUOTENAME(@Text2Quote_1,@QuoteChar_1) AS QuotedText_1,
QUOTENAME(@Text2Quote_2,@QuoteChar_1) AS QuotedText_2,
QUOTENAME(@Text2Quote_3,@QuoteChar_1) AS QuotedText_3,
QUOTENAME(@Text2Quote_4,@QuoteChar_1) AS QuotedText_4
select PARSENAME(QUOTENAME(@Text2Quote_1,@QuoteChar_1),@ParseParam) AS Parsed_QuotedText_1,
PARSENAME(QUOTENAME(@Text2Quote_2,@QuoteChar_1),@ParseParam) AS Parsed_QuotedText_2,
PARSENAME(QUOTENAME(@Text2Quote_3,@QuoteChar_1),@ParseParam) AS Parsed_QuotedText_3,
PARSENAME(QUOTENAME(@Text2Quote_4,@QuoteChar_1),@ParseParam) AS Parsed_QuotedText_4
Basically, I set a string values, output that value, QUOTENAME() and output the value, then PARSENAME() the QUOTENAME()ed value and output it.
Results
The results were quite interesting:
OriginalText_1 OriginalText_2 OriginalText_3 OriginalText_4
------------------------ ------------------------ ------------------------ ------------------------
Test [Test] Test.dbo.test [Test].[dbo].[test]
(1 row(s) affected)
QuotedText_1 QuotedText_2 QuotedText_3 QuotedText_4
------------------------ ------------------------ ------------------------ ------------------------
'Test' '[Test]' 'Test.dbo.test' '[Test].[dbo].[test]'
(1 row(s) affected)
Parsed_QuotedText_1 Parsed_QuotedText_2 Parsed_QuotedText_3 Parsed_QuotedText_4
------------------------ ------------------------ ------------------------ ------------------------
'Test' NULL test' NULL
(1 row(s) affected)
When the base text Test.dbo.test (OriginalText_3) is passed on to the QUOTENAME() function it gets converted to: 'Test.dbo.test' (QuotedText_3)
When the QuotedText_3 string 'Test.dbo.test' is passed on to the PARSENAME() function it is converted to: test' (Parsed_QuotedText_3)
Conclusion
Seeing as I have proven ypercubeᵀᴹ's thesis wrong, I think it is safe to state that the function PARSENAME() is not the inverse of QUOTENAME().
Based on Aaron Bertrand's feedback here the code for square brackets [ ] (add to original script)
Additional Code for square brackets [ ]
-- checking the results for [ brackets
SELECT @Text2Quote_1 AS OriginalText_1,
@Text2Quote_2 AS OriginalText_2,
@Text2Quote_3 AS OriginalText_3,
@Text2Quote_4 AS OriginalText_4
SELECT QUOTENAME(@Text2Quote_1,@QuoteChar_2) AS QuotedText_1,
QUOTENAME(@Text2Quote_2,@QuoteChar_2) AS QuotedText_2,
QUOTENAME(@Text2Quote_3,@QuoteChar_2) AS QuotedText_3,
QUOTENAME(@Text2Quote_4,@QuoteChar_2) AS QuotedText_4
select PARSENAME(QUOTENAME(@Text2Quote_1,@QuoteChar_2),@ParseParam) AS Parsed_QuotedText_1,
PARSENAME(QUOTENAME(@Text2Quote_2,@QuoteChar_2),@ParseParam) AS Parsed_QuotedText_2,
PARSENAME(QUOTENAME(@Text2Quote_3,@QuoteChar_2),@ParseParam) AS Parsed_QuotedText_3,
PARSENAME(QUOTENAME(@Text2Quote_4,@QuoteChar_2),@ParseParam) AS Parsed_QuotedText_4
Output for square brackets [ ]
OriginalText_1 OriginalText_2 OriginalText_3 OriginalText_4
------------------------ ------------------------ ------------------------ ------------------------
Test [Test] Test.dbo.test [Test].[dbo].[test]
(1 row(s) affected)
QuotedText_1 QuotedText_2 QuotedText_3 QuotedText_4
------------------------ ------------------------ ------------------------ ------------------------
[Test] [[Test]]] [Test.dbo.test] [[Test]].[dbo]].[test]]]
(1 row(s) affected)
Parsed_QuotedText_1 Parsed_QuotedText_2 Parsed_QuotedText_3 Parsed_QuotedText_4
------------------------ ------------------------ ------------------------ ------------------------
Test [Test] Test.dbo.test [Test].[dbo].[test]
(1 row(s) affected)
and to complete things the code for the double quotes
Additional code for double quotes "
-- checking the results for [ brackets
SELECT @Text2Quote_1 AS OriginalText_1,
@Text2Quote_2 AS OriginalText_2,
@Text2Quote_3 AS OriginalText_3,
@Text2Quote_4 AS OriginalText_4
SELECT QUOTENAME(@Text2Quote_1,@QuoteChar_3) AS QuotedText_1,
QUOTENAME(@Text2Quote_2,@QuoteChar_3) AS QuotedText_2,
QUOTENAME(@Text2Quote_3,@QuoteChar_3) AS QuotedText_3,
QUOTENAME(@Text2Quote_4,@QuoteChar_3) AS QuotedText_4
select PARSENAME(QUOTENAME(@Text2Quote_1,@QuoteChar_3),@ParseParam) AS Parsed_QuotedText_1,
PARSENAME(QUOTENAME(@Text2Quote_2,@QuoteChar_3),@ParseParam) AS Parsed_QuotedText_2,
PARSENAME(QUOTENAME(@Text2Quote_3,@QuoteChar_3),@ParseParam) AS Parsed_QuotedText_3,
PARSENAME(QUOTENAME(@Text2Quote_4,@QuoteChar_3),@ParseParam) AS Parsed_QuotedText_4
Output for double quotes "
OriginalText_1 OriginalText_2 OriginalText_3 OriginalText_4
------------------------ ------------------------ ------------------------ ------------------------
Test [Test] Test.dbo.test [Test].[dbo].[test]
(1 row(s) affected)
QuotedText_1 QuotedText_2 QuotedText_3 QuotedText_4
------------------------ ------------------------ ------------------------ ------------------------
"Test" "[Test]" "Test.dbo.test" "[Test].[dbo].[test]"
(1 row(s) affected)
Parsed_QuotedText_1 Parsed_QuotedText_2 Parsed_QuotedText_3 Parsed_QuotedText_4
------------------------ ------------------------ ------------------------ ------------------------
Test [Test] Test.dbo.test [Test].[dbo].[test]
(1 row(s) affected)
Based on ypercube™'s feedback and Aaron Bertrand's new feedback we have come to a mutual conclusion
PARSENAME() is the inverse of QUOTENAME() if the following conditions are met:
PARSENAME(x,1)-1(QUOTENAME(x,q)) where q={1,2} and x='{'any_string_value'}
References:
@QuoteChar_1as the second argument toQUOTENAME(), why? This is not a valid character for a quoted identifier.SELECT 'column', [column], "column" FROM (SELECT [column] = 1) x;IMHO, the spirit of David's comment was that by default and without adding an uncommon character as the second argument,PARSENAME()acts like the inverse ofQUOTENAME(). – Aaron Bertrand Jan 23 '18 at 14:39'(single quotes),"(double quotes) and[ ](square brackets) are valid quotation marks for the functionQUOTENAME. I'll add more examples. – John K. N. Jan 23 '18 at 15:00QUOTENAME(). It's that we don't use them in SQL Server to quote identifiers, and the question was clearly in the context of parsing identifiers. – Aaron Bertrand Jan 23 '18 at 15:21PARSENAME()is the opposite ofQUOTENAME()IFQUOTENAME()is limited to"(double quotes) and[ ](square brackets) AND the parameterobject_piecefor thePARSENAME()function is limited to1? – John K. N. Jan 23 '18 at 15:29PARSENAME(x , 1)is the inverse ofQUOTENAME(x, q)whenqis not the single quote ;) – ypercubeᵀᴹ Jan 23 '18 at 15:56