String = 'DOB; 04 March 1999; Passport; ABC123'
I have some data present in the above format. I want to save it in a SQL table in a single row. But only the date of birth and passport number present on second and fourth position. Sometimes data can be changed like this:
String = 'DOB; March 04; Passport; 12345'
OR
String = 'DOB; March 04'
OR
String = 'Passport; ABC123'
What should be my approach? I have to do this using only SQL functions or queries.
I have tried different things like Stringsplit, cursor, parsename, substring, charindex etc but can't get the required result I need.
DECLARE @string2 varchar(max) = 'DOB;Mar 1199;Passport;W123333';
DECLARE @sep char(1) = ';'
, @dot CHAR(1) = '.';
DECLARE @employee TABLE (
id INT IDENTITY(1,1) PRIMARY KEY,
Dob1 varchar(20),
DobNum VARCHAR(20),
Pass1 VARCHAR(20),
PassNum VARCHAR(20)
);
Thanks in advance...
EDIT @Dale:
DECLARE @string3 varchar(max) = 'DOB; MARCH 1999; Passport; ABC123';
DECLARE @sep3 char(1) = ';'
DECLARE @dot3 char(1) = '.'
DECLARE @tab3 TABLE(
id INT IDENTITY(1,1) PRIMARY KEY,
Dob1 varchar(max),
Dobnum varchar(max),
Pass1 varchar(max),
Passnum varchar(max)
);
WITH QUERY1 as
(
SELECT REPLACE(@string3, @sep3, @dot3) as ABClist
)
INSERT into @tab3 (DobNum,PassNum)
SELECT PARSENAME (ABCList,3),
PARSENAME (ABCList,1)
FROM QUERY1
--TEST
select * from @tab3
select Dobnum, Passnum from @tab3
--cursor
declare
@Dobnum2 varchar(max),
@Passnum2 varchar(max);
declare cursor3 CURSOR for
select Dobnum,Passnum from @tab3
OPEN cursor3;
FETCH next from cursor3 into
@Dobnum2, @Passnum2
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @Dobnum2 + @Passnum2
INSERT INTO [dbo].[EMPLOYEE]
(dobnum,passnum
)
values
( @Dobnum2, @Passnum2)
FETCH next from cursor3 into
@Dobnum2, @Passnum2
END;
Close cursor3;
Deallocate cursor3;
The complicated part of your scenario is that the ordinal positions of the DOB
and Passport
substrings are not always at second and forth position. But, a JSON-based approach is a possible option here. You need to transform the input string into a valid JSON object with a specific structure ( DOB;Mar 1199;Passport;W123333
into {"DOB":"Mar 1199","Passport":"W123333"}
) and parse the generated JSON using OPENJSON()
and explicit schema:
DECLARE @string varchar(max) = 'DOB;Mar 1199;Passport;W123333';
INSERT INTO @employee (DobNum, PassNum)
SELECT DobNum, PassNum
FROM OPENJSON (CONCAT(
'{"',
REPLACE(
REPLACE(
REPLACE(
@String,
'DOB;',
'DOB":"'
),
'Passport;',
'Passport":"'
),
';',
'","'
),
'"}'
)
) WITH (
DobNum varchar(20) '$.DOB',
PassNum varchar(20) '$.Passport'
) j
Use STRING_SPLIT
and dynamic pivot
create table employee (
id INT IDENTITY(1,1) PRIMARY KEY,
Dob1 varchar(20),
DobNum VARCHAR(20),
Pass1 VARCHAR(20),
PassNum VARCHAR(20)
);
create table temp(col varchar(20))
insert into temp
select * FROM STRING_SPLIT('DOB; 04 March 1999; Passport; ABC123',';')
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.col)
FROM temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
set @query = 'insert into employee SELECT ' + @cols + ' from
(
select col
from temp
) x
pivot
(
max(col)
for col in (' + @cols + ')
) p '
execute(@query)
Just to throw a different idea out there as well. One method would be to use a string splitter that provides the ordinal position (such as the JSON splitter I use here), to get the values into column name/column value pairs, and then use conditional aggregation to normalise, and INSERT
:
WITH CTE AS(
SELECT MAX(CASE WHEN DSJ.[Position] % 2 = 0 THEN TRIM(DSJ.Item) END) AS ColumnName,
MAX(CASE WHEN DSJ.[Position] % 2 = 1 THEN TRIM(DSJ.Item) END) AS ColumnValue
FROM fn.DelimitedSplitJSON(@String,';') DSJ
GROUP BY DSJ.[Position] / 2)
INSERT INTO @employee (DobNum, PassNum)
SELECT MAX(CASE ColumnName WHEN 'DOB' THEN ColumnValue END),
MAX(CASE ColumnName WHEN 'Passport' THEN ColumnValue END)
FROM CTE;
JSON splitter definition:
CREATE FUNCTION [fn].[DelimitedSplitNJSON] (@String nvarchar(MAX), @Delimiter nvarchar(10))
RETURNS TABLE
AS RETURN
SELECT [value] AS Item,
[key] AS Position
FROM OPENJSON(N'["' + REPLACE(@String,@Delimiter,N'","') + N'"]"');
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.