If you are looking for a TSQL solution, and if the result table should look like the diagram below:
| DISMISS_SETTING | SHOW_SETTING | DEFAULT_SETTING | |-----------------|--------------|-----------------| | DEFAULT | DEFAULT | DEFAULT |
you should use a set of scripts that I will describe in a minute. Initially, you need to create a dynamic stored procedure that builds dynamic queries - it gives you the opportunity to insert your data into the table under columns whose names are unknown until runtime (XML parsing time):
create procedure mysp_update (@table_name nvarchar(50), @column_name nvarchar(50), @column_value nvarchar(50)) as begin declare @rows_count int declare @query nvarchar(500) declare @parm_definition nvarchar(100) -- Get rows count in your table using sp_executesql and an output parameter set @query = N'select @rows_count = count(1) from ' + quotename(@table_name) exec sp_executesql @query, N'@rows_count INT OUTPUT', @rows_count OUTPUT -- If no rows - insert the first one, else - update existing if @rows_count = 0 set @query = N'insert into ' + quotename(@table_name) + N'(' + quotename(@column_name) + N') values (@column_value)' else set @query = N'update ' + quotename(@table_name) + N'set ' + quotename(@column_name) + N' = @column_value' set @parm_definition = N'@column_value nvarchar(50)' exec sp_executesql @query, @parm_definition, @column_value = @column_value end go
Next, use this XQuery / SQL statement to extract (from XML) the information you are looking for:
-- Define XML object based on which insert statement will be later created declare @data xml = N'<properties> <property> <name>DISMISS_SETTING</name> <value>DEFAULT</value> </property> <property> <name>SHOW_SETTING</name> <value>DEFAULT</value> </property> <property> <name>DEFAULT_SETTING</name> <value>DEFAULT</value> </property> </properties>' -- Declare temporary container declare @T table(id int identity, name nvarchar(50), value nvarchar(50)) -- Push the extracted nodes values into it insert into @T(name, value) select x.value(N'(name)[1]', N'nvarchar(50)'), x.value(N'(value)[1]', N'nvarchar(50)') from @data.nodes(N'/properties/property') AS XTbl(x)
After that, the extracted data pairs [name, value] are stored in the table variable @T . Finally, repeat this temporary metadata and paste the values ββinto the appropriate column names of your main table:
declare @name nvarchar(50), @value nvarchar(50), @current_id int = 1 -- Fetch first row select @name = name, @value = value from @T where id = @current_id while @@rowcount = 1 begin -- Execute SP here (btw: SP cannot be executed from select statement) exec mysp_update N'TableName', @name, @value -- Fetch next row set @current_id = @current_id + 1 select @name = name, @value = value from @T where id = @current_id end
The presented solution allows you to have a variable number of nodes in XML, provided without any specific order.
Note that the logic responsible for retrieving data from XML and pasting it into the main table can be wrapped in an additional stored procedure, for example. mysp_xml_update (@data xml) and then executed as follows: exec mysp_xml_update N'<properties>....</properties> .
However, try the code itself using SQL Fiddle .
UPDATE:
As stated in the comment, one big update should be done instead of sequentially updating the column by column. To do this, mysp_update should be changed, for example. in the following way:
create type HashTable as table(name nvarchar(50), value nvarchar(50)) go create procedure mysp_update (@table_name nvarchar(50), @set HashTable readonly) as begin -- Concatenate names and values (to be passed to insert statement below) declare @columns varchar(max) select @columns = COALESCE(@columns + ', ', '') + quotename(name) from @set declare @values varchar(max) select @values = COALESCE(@values + ', ', '') + quotename(value, '''') from @set -- Remove previous values declare @query nvarchar(500) set @query = N'delete from ' + quotename(@table_name) -- Insert new values to the table exec sp_executesql @query set @query = N'insert into ' + quotename(@table_name) + N'(' + @columns + N') values (' + @values + N')' exec sp_executesql @query end go