Question :
I have a SQL Server table with one specific nvarchar column (let’s assume it’s called details
) having data like below:
Item1: A100 ; Item2: B200; Item3:C300: Item4:D400; Item5:E500; Item6: F600600600; Item7: ;Item8: H800
I am looking to parse this specific column details
in the table and store each item value in individual columns through a SQL view so that I can use it for querying individual elements/reporting.
The item labels/descriptions Item1
, Item2
etc will remain the same, so I may not need to extract that. Their number is expected to be fixed as well.
However I need to extract each item value between the :
and ;
and have them assigned to Item1value
, Item2value
in my view.
And sometimes some values may be simply null like shown in the sample above.
create view v_name as
select ___ as Item1Value, ___ as Item2Value...
from details
How can this be accomplished?
Answer :
This is a pretty boring answer, but if you are guaranteed to always have your data in that format then you can get your desired results with a bunch of CHARINDEX and SUBSTRING calls. The idea is that if you find all of the positions of the labels you can take advantage of their fixed lengths to use those positions in the arguments of the SUBSTRING
calls.
By the way, it looks like you have a few typos in your sample data. I’ve attempted to fix them so pay special attention to my test data.
CREATE TABLE #DETAILS (TEST_STRING VARCHAR(1000));
INSERT INTO #DETAILS VALUES ('Item1: A100 ; Item2: B200; Item3:C300; Item4:D400; Item5:E500; Item6: F600600600; Item7:; Item8: H800');
INSERT INTO #DETAILS VALUES ('Item1:; Item2:; Item3:; Item4:; Item5:; Item6:; Item7:; Item8:');
SELECT
SUBSTRING(TEST_STRING, 7, P2 - 7) ITEM1VALUE
, SUBSTRING(TEST_STRING, P2 + 8, P3 - P2 - 8) ITEM2VALUE
, SUBSTRING(TEST_STRING, P3 + 8, P4 - P3 - 8) ITEM3VALUE
, SUBSTRING(TEST_STRING, P4 + 8, P5 - P4 - 8) ITEM4VALUE
, SUBSTRING(TEST_STRING, P5 + 8, P6 - P5 - 8) ITEM5VALUE
, SUBSTRING(TEST_STRING, P6 + 8, P7 - P6 - 8) ITEM6VALUE
, SUBSTRING(TEST_STRING, P7 + 8, P8 - P7 - 8) ITEM7VALUE
, SUBSTRING(TEST_STRING, P8 + 8, 8000) ITEM8VALUE
FROM
(
SELECT
TEST_STRING
, CHARINDEX('; Item2:', TEST_STRING) P2
, CHARINDEX('; Item3:', TEST_STRING) P3
, CHARINDEX('; Item4:', TEST_STRING) P4
, CHARINDEX('; Item5:', TEST_STRING) P5
, CHARINDEX('; Item6:', TEST_STRING) P6
, CHARINDEX('; Item7:', TEST_STRING) P7
, CHARINDEX('; Item8:', TEST_STRING) P8
FROM #DETAILS
) t;
Results (bottom row is all nulls as expected):
╔════════╦═══════╦═══════╦═══════╦═══════╦═════════════╦═══════╦═══════╗
║ ITEM1 ║ ITEM2 ║ ITEM3 ║ ITEM4 ║ ITEM5 ║ ITEM6 ║ ITEM7 ║ ITEM8 ║
╠════════╬═══════╬═══════╬═══════╬═══════╬═════════════╬═══════╬═══════╣
║ A100 ║ B200 ║ C300 ║ D400 ║ E500 ║ F600600600 ║ ║ H800 ║
║ ║ ║ ║ ║ ║ ║ ║ ║
╚════════╩═══════╩═══════╩═══════╩═══════╩═════════════╩═══════╩═══════╝
The above code will not work if you don’t always have exactly eight items and you don’t always have a space between ;
and the next item label (except for label 1 of course). Also note that your item values cannot contain certain values or the code will throw an error. You said that you just want to get the data between :
and ;
and generally delimiters should not show up in data, but here’s an example of data that would cause an issue:
INSERT INTO #DETAILS VALUES ('Item1:; Item7:; Item2:; Item3:; Item4:; Item5:; Item6:; Item7:; Item8:');
Easy way is to create this split function and use SUBSTRING and CHARINDEX over the data returned by the function.
CREATE FUNCTION [dbo].[fnSplitString]
(
@string NVARCHAR(MAX),
@delimiter CHAR(1)
)
RETURNS @output TABLE(splitdata NVARCHAR(MAX)
)
BEGIN
DECLARE @start INT, @end INT
SELECT @start = 1, @end = CHARINDEX(@delimiter, @string)
WHILE @start < LEN(@string) + 1 BEGIN
IF @end = 0
SET @end = LEN(@string) + 1
INSERT INTO @output (splitdata)
VALUES(SUBSTRING(@string, @start, @end - @start))
SET @start = @end + 1
SET @end = CHARINDEX(@delimiter, @string, @start)
END
RETURN
END
GO
DECLARE @STRING NVARCHAR(MAX)='Item1: A100 ; Item2: B200; Item3:C300; Item4:D400; Item5:E500; Item6: F600600600; Item7: ;Item8: H800'
DECLARE @TABLE TABLE ([Item] NVARCHAR(124))
INSERT INTO @TABLE
SELECT SUBSTRING(splitdata,CHARINDEX(':',splitdata)+1,LEN(splitdata)) FROM [dbo].[fnSplitString] (@STRING,';');
Thanks