How to create a table of name-value pairs in SQL
sql
Solution
Basically you have two problems - to `UNPIVOT`, the data types have to be conformed. The other problem is that the number of columns is unknown. You want to reach something of the form:
WITH conformed
AS ( SELECT CONVERT(VARCHAR(255), [Firstname]) AS [Firstname],
CONVERT(VARCHAR(255), [Surname]) AS [Surname],
CONVERT(VARCHAR(255), [Address1]) AS [Address1],
CONVERT(VARCHAR(255), [City]) AS [City],
CONVERT(VARCHAR(255), [Country]) AS [Country]
FROM so1526080
)
SELECT ColumnKey,
ColumnValue
FROM conformed UNPIVOT ( ColumnValue FOR ColumnKey IN ( [Firstname], [Surname], [Address1], [City], [Country] ) ) AS unpvt
So using a dynamic SQL PIVOT using metadata (you might need to fix this up with TABLE_SCHEMA, etc):
DECLARE @table_name AS SYSNAME
SET @table_name = 'so1526080'
DECLARE @conform_data_type AS VARCHAR(25)
SET @conform_data_type = 'VARCHAR(255)'
DECLARE @column_list AS VARCHAR(MAX)
DECLARE @conform_list AS VARCHAR(MAX)
SELECT @conform_list = COALESCE(@conform_list + ', ', '') + 'CONVERT('
+ @conform_data_type + ', ' + QUOTENAME(COLUMN_NAME) + ') AS '
+ QUOTENAME(COLUMN_NAME),
@column_list = COALESCE(@column_list + ', ', '')
+ QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table_name
DECLARE @template AS VARCHAR(MAX)
SET @template = '
WITH conformed
AS ( SELECT {@conform_list}
FROM {@table_name}
)
SELECT ColumnKey,
ColumnValue
FROM conformed UNPIVOT ( ColumnValue FOR ColumnKey IN ( {@column_list} ) ) AS unpvt
'
DECLARE @sql AS VARCHAR(MAX)
SET @sql = REPLACE(REPLACE(REPLACE(@template, '{@conform_list}', @conform_list),
'{@column_list}', @column_list), '{@table_name}',
@table_name)
PRINT @sql
EXEC ( @sql
)
Problem
Using SQL, how do I convert a single row table like this... ``` Firstname Surname Address1 City Country --------- ------- --------------- ------ ------- Bob Smith 101 High Street London UK ``` ...to a table of name-value pairs like this: ``` Name Value --------- ------- Firstname Bob Surname Smith Address1 101 High Street City London Country UK ``` This script will create the original table: ``` create table #OriginalTable (Firstname varchar(10), Surname varchar(10), Address1 varchar(50), City varchar(10), Country varchar(10)) insert into #OriginalTable select 'Bob' Firstname, 'Smith' Surname, '101 High Street' Address1, 'London' City, 'UK' Country ``` I'm after a generic solution that does not depend on the columns names always being what they are in the example. EDIT: I'm using SQL Server 2005. The solution I'm after is the SQL script to convert this data into a name-value pair table ANSWER: Using the answer that I accepted as the answer, this is what I've used: ``` select result.Name, result.Value from (select convert(sql_variant,FirstName) AS FirstName, convert(sql_variant,Surname) AS Surname, convert(sql_variant,Address1) AS Address1, convert(sql_variant,City) AS City, convert(sql_variant,Country) AS Country from #OriginalTable) OriginalTable UNPIVOT (Value For Name In (Firstname, Surname, Address1, City, Country)) as result ```