0

Goal

I'm trying to create a stored procedure that would take @tableName VARCHAR(MAX) and @id INT and return a list of key-value pairs, that is, a table with 2 columns called ColumnName VARCHAR(MAX) and ColumnValue VARCHAR(MAX) which would be populated with column names and values from a simple query that selects all columns from @tableName where [Id] = @id.

Example

Let's say we have a table

Person

Id FirstName LastName Nickname
1 John Johnson Jonny
2 Sally Johnson Sal
...

and then we call the stored procedure

EXEC spConvertToKeyValuePairs 'Person', 2

and the output of the stored procedure would be

ColumnName ColumnValue
Id 2
FirstName Sally
LastName Johnson
Nickname Sal

What I made so far

I got to the point where I have column names

CREATE PROCEDURE [dbo].[spConvertToKeyValuePairs]
    @tableName VARCHAR(MAX),
    @id INT
AS
    DECLARE @valTable TABLE(ColumnName VARCHAR(MAX), ColumnValue VARCHAR(MAX))

    INSERT INTO @valTable (ColumnName, ColumnValue)
        SELECT [COLUMN_NAME] 
            FROM INFORMATION_SCHEMA.COLUMNS
            WHERE [TABLE_NAME] = @tablename

    SELECT * FROM @valTable

    -- and now I don't know how to add row values

RETURN 0

We are not talking about ___ in this question

  • Tables that don't have Id INT PRIMARY KEY IDENTITY(1,1) column

  • Security risks

Question

Can you help me finish / redesign this stored procedure to get the output I need?

Monset
  • 648
  • 5
  • 25
  • 2
    This seems a very unusual requirement but you're looking for a *dynamic pivot* - plenty of solutions exist on Stack Overflow and elsewhere. Also, why `varchar(max)`? A column is always `sysname` – Stu Sep 12 '22 at 10:59
  • I understand the dynamic part, i understand the pivot part but even after playing a bit with pivot I can't get my head around it, and I found a seemingly good solution for dynamic pivot, but when I tested it it wasn't so... dynamic. Or rather I didn't understand it good enough to edit it to work for me. I'm talking about 4th code sample from accepted answer for this question https://stackoverflow.com/questions/13372276/simple-way-to-transpose-columns-and-rows-in-sql . `sysname` is just `varchar(128)`, yes? I could change that, no need for `max` to be there. – Monset Sep 12 '22 at 11:06
  • I would suggest forgetting using `pivot` and using a *conditional case expression* approach, it's a lot easier to work with and more flexable, imho. – Stu Sep 12 '22 at 11:13
  • 1
    Aside: Is it a coincidence that the all of the columns other than `Id` in your universe of discourse happen to be `VARCHAR(MAX)`? That eliminates any issues like how to convert various date/time data types and other challenges into strings, ... . Spatial data. Node and edge tables. – HABO Sep 12 '22 at 12:58
  • hahaha no no, I'm just concetrating on making things work for now. I makes no sense to leave it at `VARCHAR(MAX)`, at least not now. I'm just focusing on making it workable for now. None of my columns in other tables are of that type nor are any of parameters of other procedures of that type, nor will that be the case this time. – Monset Sep 12 '22 at 13:03
  • Does that mean that `ColumnValue` will really be a [`sql_variant`](https://learn.microsoft.com/en-us/sql/t-sql/data-types/sql-variant-transact-sql?view=sql-server-ver16)? It almost sounds good until you start to look at some of the [restrictions](https://learn.microsoft.com/en-us/sql/t-sql/data-types/sql-variant-transact-sql?view=sql-server-ver16#restrictions) on `sql_deviant` _[sic]_ data. And a few other details under [remarks](https://learn.microsoft.com/en-us/sql/t-sql/data-types/sql-variant-transact-sql?view=sql-server-ver16#remarks). – HABO Sep 12 '22 at 20:15
  • no no, i just need varchar as result. It's for string representation to UI. I will not be putting anything crazy in there. And if I ever need to put anything crazy in there, I'd probably try to add one more column in this output table called `ColumnType` so I know if the string representation represents an image url or... well... maybe some other file type url or something, idk... for now Serg's answer works just fine. – Monset Sep 14 '22 at 10:49

1 Answers1

1

A static version using JSON functions

select b.[Key] col, b.[Value] value
from yourTable a
cross apply OpenJson(
  (select a.* 
   for JSON PATH, WITHOUT_ARRAY_WRAPPER, INCLUDE_NULL_VALUES)  
) b
where Id = @id

As you said, you should build a dynamic sql and use sp_executesql to run it with a parameter.

Demo

Serg
  • 22,285
  • 5
  • 21
  • 48