How can I write this SQL while loop code to get an XML results in one line instead of 3 separate lines? - sql

I'm trying to get all this XML result in one line instead of 3 for each column
DECLARE #ii INT = 10;
DECLARE #String1 NVARCHAR(4000);
SET #String1 = '';
WHILE(#ii <= 18)
BEGIN
SET #String1 = (#String1 + 'SELECT LoanNumber = ''Complaint'+CONVERT(VARCHAR(2),#ii)+'-Call1'' , LoanStatus=''Compliants'' , LoanStatusDate = CAST(GETDATE() AS DATE)
UNION
SELECT LoanNumber = ''Complaint'+CONVERT(VARCHAR(2),#ii)+'-Call2'', LoanStatus=''Compliants'' , LoanStatusDate = CAST(GETDATE() AS DATE)
UNION
SELECT LoanNumber = ''Complaint'+CONVERT(VARCHAR(2),#ii)+'-Call3'', LoanStatus=''Compliants'' , LoanStatusDate = CAST(GETDATE() AS DATE)')
IF #ii != 18
SET #string1 = #string1 + ' UNION '
ELSE
SET #string1 = #string1 + 'FOR XML PATH (''Loan''),ROOT(''Loans'') '
SET #ii = #ii+1
END
EXEC sp_executesql #String1
I want something like this:
<Loans>
<LoanNumber>Complaint10-Call1<LoanStatus>Compliants<LoanStatusDate>2019-01-18
</Loan>
<Loan>
<LoanNumber>Complaint10-Call2 <LoanStatus>Compliants<LoanStatusDate>2019-01-18
</Loan>
<Loan>
<LoanNumber>Complaint10-Call3<LoanStatus>Compliants<LoanStatusDate>2019-01-18
</Loan>
Instead of the result that you get when you execute the code I provided. I appreciate your help.

This might be wild guessing, but I've got the feeling, that I understand, what this is about:
if you run the code you will see the result. no input data is needed .
I just want the structure of the xml outcome to all be on one line for
one set of each loop
Your provided code leads to this:
<Loans>
<Loan>
<LoanNumber>Complaint10-Call1</LoanNumber>
<LoanStatus>Compliants</LoanStatus>
<LoanStatusDate>2019-01-22</LoanStatusDate>
</Loan>
<Loan>
<LoanNumber>Complaint10-Call2</LoanNumber>
<LoanStatus>Compliants</LoanStatus>
<LoanStatusDate>2019-01-22</LoanStatusDate>
</Loan>
<!-- more of them-->
</Loans>
This is perfectly okay, valid XML.
But you want the result
outcome to all be on one line for one set of each loop
Something like this?
<Loans>
<Loan>
<LoanNumber>Complaint10-Call1</LoanNumber><LoanStatus>Compliants</LoanStatus><LoanStatusDate>2019-01-22</LoanStatusDate>
</Loan>
<!-- more of them-->
</Loans>
There is a big misconception I think... XML is not the thing you see. The same XML can look quite differently, without any semantic difference:
Check this out:
DECLARE #xmltable table(SomeXml XML)
INSERT INTO #xmltable VALUES
--the whole in one line
('<root><a>test</a><a>test2</a></root>')
--all <a>s in one line
,('<root>
<a>test</a><a>test2</a>
</root>')
--each element in one line
,('<root>
<a>test</a>
<a>test2</a>
</root>')
--white space going wild...
,('<root>
<a>test</a>
<a>test2</a>
</root>');
--now check the results
SELECT * FROM #xmltable;
This means: How the XML appears is a matter of the interpreter. The same XML opened with another tool might appear differently. Dealing with XML means dealing with data but not with format... The actual format has no meaning and should not matter at all...
Starting with SQL-Server 2016 you might have a look at JSON, if you need a tiny format:
DECLARE #somedata table(SomeValue VARCHAR(100),SomeStatus VARCHAR(100),SomeDate DATE);
INSERT INTO #somedata VALUES
('Complaint10-Call1','Complaints','2019-01-22')
,('Complaint10-Call2','Complaints','2019-01-22')
,('Complaint10-Call3','Complaints','2019-01-22');
SELECT * FROM #somedata FOR JSON PATH;
The result comes in one line:
[{"SomeValue":"Complaint10-Call1","SomeStatus":"Complaints","SomeDate":"2019-01-22"},{"SomeValue":"Complaint10-Call2","SomeStatus":"Complaints","SomeDate":"2019-01-22"},{"SomeValue":"Complaint10-Call3","SomeStatus":"Complaints","SomeDate":"2019-01-22"}]

Related

Insert data from Aliases

enter image description hereI have Cyrillic text for input and Latin for output. in Cyrillic I have a variable and I can insert it in a table
But how can I create a variable for the output as well.
I also need to create a variable for EN (output parameters) so that I can insert it into a table or if there is another option.
DECLARE #TEXT NVARCHAR(1000)
SET #TEXT = 'Днес'
DECLARE #EN NVARCHAR(1000)
SET #EN =''
insert into [Anatoli].[dbo].[logg]([date1],lo,[lo1]) values(GETDATE(),#TEXT,ЕN)
SELECT
#TEXT as BG
,replace(replace(replace(replace(replace(replace
(replace(replace(replace(replace(replace(replace(replace(replace
(replace(replace(replace(replace(replace(replace(replace(replace(replace
(replace(replace(replace(replace(replace(replace(replace
(#TEXT,'и','i'),'в','v'),'а','a'),'н','n'),'б','b' )
,'г','g'),'д','d'),'e','е'),'ж','zh'),'з','z'),'й','y'),'к','k')
,'л','l'),'м','m'),'о','o'),'п','p'),'р','r'),'с','s'),'т','t'),'у','u')
,'ф','f'),'х','h'),'ц','ts'),'ч','ch'),'ш','sh'),'щ','sht'),'ъ','a'),'ь','y')
,'ю','yu'),'я','yа') AS EN
Expected result
on the picture
If your Cyrillic-Latin translation needs to be reusable it's going to be most versatile in an Inline Table-Valued Function, e.g.:
create function dbo.app_CyrillicToLatin(
#Cyrillic nvarchar(1000)
)
returns table as
return (
select [Latin] =
replace(replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(#Cyrillic,
N'и', N'i'), N'в', N'v'), N'а', N'a'), N'н', N'n'), N'б', N'b' ),
N'г', N'g'), N'д', N'd'), N'е', N'e'), N'ж', N'zh'), N'з', N'z'),
N'й', N'y'), N'к', N'k'), N'л', N'l'), N'м', N'm'), N'о', N'o'),
N'п', N'p'), N'р', N'r'), N'с', N's'), N'т', N't'), N'у', N'u'),
N'ф', N'f'), N'х', N'h'), N'ц', N'ts'), N'ч', N'ch'), N'ш', N'sh'),
N'щ', N'sht'), N'ъ', N'a'), N'ь', N'y'), N'ю', N'yu'), N'я', N'yа')
);
go
This gives you the flexibility to set variables, as requested, as well as translate in a set-based fashion for INSERT, UPDATE and SELECT operations...
-- Usage 1, setting a variable
select #EN = Latin
from dbo.app_CyrillicToLatin(#TEXT);
-- Usage 2, translating during insert...
insert into [dbo].[logg] ([date1], [lo], [lo1])
select getdate(), #TEXT, Latin
from dbo.app_CyrillicToLatin(#TEXT);
-- Usage 3, translating during update...
update L
set [lo1] = Latin
from [dbo].[logg] L
cross apply dbo.app_CyrillicToLatin([lo]);
-- Usage 4, translating during select...
select [date1], [lo], [Latin] as [lo1]
from [dbo].[logg]
cross apply dbo.app_CyrillicToLatin([lo]);

Error Handling for numbers of delimiters when extracting substrings

Situation: I have a column where each cell can have up to 5 delimiters. However, it's possible that there are none.
Objective: How do i handle errors such as :
Invalid length parameter passed to the LEFT or SUBSTRING function.
in the case that it cannot find the specified delimiter.
Query:
declare #text VARCHAR(111) = 'abc-def-geeee-ifjf-zzz'
declare #start1 as int
declare #start2 as int
declare #start3 as int
declare #start4 as int
declare #start_index_reverse as int
set #start1 = CHARINDEX('-',#text,1)
set #start2 = CHARINDEX('-',#text,charindex('-',#text,1)+1)
set #start3 = CHARINDEX('-',#text,charindex('-',#text,CHARINDEX('-',#text,1)+1)+1)
set #start4 = CHARINDEX('-',#text,charindex('-',#text,CHARINDEX('-',#text,CHARINDEX('-',#text,1)+1)+1)+1)
set #start_index_reverse = CHARINDEX('-',REVERSE(#text),1)
select
LEFT(#text,#start1-1) AS Frst,
SUBSTRING(#text,#start1+1,#start2-#start1-1) AS Scnd,
SUBSTRING(#text,#start2+1,#start3-#start2-1) AS Third,
SUBSTRING(#text,#start3+1,#start4-#start3-1)AS Third,
RIGHT(#text,#start_index_reverse-1) AS Lst
In this case my variable includes 5 delimiters and so my query works but if i removed one '-' it would break.
XML support in SQL Server brings about some unintentional but useful tricks. Converting this string to XML allows for some parsing that is far less messy than native string handling, which is very far from awesome.
DECLARE #test varchar(111) = 'abc-def-ghi-jkl-mnop'; -- try also with 'abc-def'
;WITH n(x) AS
(
SELECT CONVERT(xml, '<x>' + REPLACE(#test, '-', '</x><x>') + '</x>')
)
SELECT
Frst = x.value('/x[1]','varchar(111)'),
Scnd = x.value('/x[2]','varchar(111)'),
Thrd = x.value('/x[3]','varchar(111)'),
Frth = x.value('/x[4]','varchar(111)'),
Ffth = x.value('/x[5]','varchar(111)')
FROM n;
For a table it's almost identical:
DECLARE #foo TABLE ( col varchar(111) );
INSERT #foo(col) VALUES('abc-def-ghi-jkl-mnop'),('abc'),('def-ghi');
;WITH n(x) AS
(
SELECT CONVERT(xml, '<x>' + REPLACE(col, '-', '</x><x>') + '</x>')
FROM #foo
)
SELECT
Frst = x.value('/x[1]','varchar(111)'),
Scnd = x.value('/x[2]','varchar(111)'),
Thrd = x.value('/x[3]','varchar(111)'),
Frth = x.value('/x[4]','varchar(111)'),
Ffth = x.value('/x[5]','varchar(111)')
FROM n;
Results (sorry about the massive size, seems this doesn't handle 144dpi well):
add a test before your last select
then you should decide how to handle the other case (when one of start is 0)
You can also refer to this link about splitting a string in sql server
which is uses a loop and can handle any number of delimiters
if #start1>0 and #start2>0 and #start3>0 and #start4>0
select LEFT(#text,#start1-1) AS Frst,
SUBSTRING(#text,#start1+1,#start2-#start1-1) AS Scnd,
SUBSTRING(#text,#start2+1,#start3-#start2-1) AS Third,
SUBSTRING(#text,#start3+1,#start4-#start3-1)AS Third,
RIGHT(#text,#start_index_reverse-1) AS Lst

Can Multiple Parameter be used with LIKE in SQL

I am getting data from database in a format like "chem*,bio*" what i want to do is after i split the string into two i want to fetch all records containing "chem" and "bio" .. using LIKE with multiple parameter is something i want since CONTAIN will bring in irrelevant data too. Kindly help.
its something like this
assume:
#cwork2 ='chem*,bio*'
#cw1=#cw1 +'OR contains (name,'''+#Cwork1+''')'
#cw1=#cw1 +'OR name LIKE ('''+#Cwork1+''','%')'
Try this:
You can use pipeline (|) to achieve Or Condition
select * from Tablename where name like '[chem|bio]%';
just add them in an OR condition.
#cw1 = #cw1 OR name like '%chem%' OR name like '%bio%'
i found another way... although he answers provided are right on track but when talking about variables we cannot simply add on variables in the code. Hence forth i decided to put the variable in a #temp table, loop it through and then accordingly fetch data
insert into #publication select item from fsplit(#Work,',')
Declare #loopc int=1
while (#loopc <= (SELECT count(*) from #pub))
Begin
set #Cwork1= (select name from #pub where id= #loopc);
if CHARINDEX(#Cwork1,'*')<0
Begin
set #cw1='or pub.name ='''+#Cwork1+''')'
end
else
begin
set #Cwork1 = REPLACE(#Cwork1,'*','%');
set #cw1=#cw1 +'OR pub.name LIKE ('''+#Cwork1+''')'
end
set #loopc= #loopc +1;
end
set #cw1= (SELECT STUFF(#cw1, CHARINDEX('or', #cw1), LEN('or'), ''))
set #cw1= '('+#cw1+')'
set #Au2= #Au2 + ' and '+ #cw1

Update(Replace partcial value) XML Column in SQL

I have an XML column in my Table and i wanted to replace particular text wherever it appear in that column with a new text. Here is the xml structure,
<Story>
<StoryNonText>
<NonText>
<ImageID>1</ImageID>
<Src>http://staging.xyz.com/FolderName/1.png</Src>
</NonText>
<NonText>
<ImageID>2</ImageID>
<Src>http://staging.xyz.com/FolderName/2.png</Src>
</NonText>
</StoryNonText>
</Story>
In the above XML I wanted to replace all the <Src> values having http://staging.xyz.com/ to http://production.xyz.com/. Please guide me how i can do this!
You can use Replace() function as below:
Update TableName
SET
ColumnName=replace(CAST(ColumnName AS VARCHAR(8000)),'<Src>http://staging.xyz.com/','<Src>http://production.xyz.com/')
With a little help from a couple of XML functions you can do this in a loop.
The loop is necessary since replace value of can only replace one value at a time. This code assumes the URL is located first in the node and not embedded in text anywhere.
declare #T table(X xml);
insert into #T(X) values('<Story>
<StoryNonText>
<NonText>
<ImageID>1</ImageID>
<Src>http://staging.xyz.com/FolderName/1.png</Src>
</NonText>
<NonText>
<ImageID>2</ImageID>
<Src>http://staging.xyz.com/FolderName/2.png</Src>
</NonText>
</StoryNonText>
</Story> ');
declare #FromURL nvarchar(100);
declare #ToURL nvarchar(100);
set #FromURL = 'http://staging.xyz.com/';
set #ToURL = 'http://production.xyz.com/';
while 1 = 1
begin
update #T
set X.modify('replace value of (//*/text()[contains(., sql:variable("#FromURL"))])[1]
with concat(sql:variable("#ToURL"), substring((//*/text()[contains(., sql:variable("#FromURL"))])[1], string-length(sql:variable("#FromURL"))+1))')
where X.exist('//*/text()[contains(., sql:variable("#FromURL"))]') = 1;
if ##rowcount = 0
break;
end;
select *
from #T
replace value of (XML DML)
concat Function (XQuery)
contains Function (XQuery)
string-length Function (XQuery)
sql:variable() Function (XQuery)
There are many ways to do that.
The first way is to add a WHILE loop. Inside a loop, you search (CHARINDEX) for a position of first tag and first tag. Then, knowing the start and end positions, replace the value. Then on the next iteration you search again, but change starting position in CHARINDEX() function
The second way is to use SELECT ... FROM OPENXML + EXEC sp_xml_preparedocument

MS-SQL - Extracting numerical portion of a string

I have an MS-SQL table, with a column titled 'ImportCount'.
Data in this column follows the below format:
ImportCount
[Schedules] 1376 schedule items imported from location H:\FOLDERA\AA\XX...
[Schedules] 10201 schedule items imported from location H:\FOLDERZZ\PERS\YY...
[Schedules] 999 schedule items imported from location R:\PERS\FOLDERA\AA\XX...
[Schedules] 21 schedule items imported from location H:\FOLDERA\MM\2014ZZ...
What I would like to do is extract that numerical portion of the data (which varies in length), but am struggling to get the right result. Would appreciate any help on this!
Thanks.
Try
select left(ImportCount, patindex('%[^0-9]%', ImportCount+'.') - 1)
select SUBSTRING(ImportCount,13,patindex('% schedule items%',ImportCount)-13) from table name
Try this..You can declare it as a SQL function also.
DECLARE #intText INT
DECLARE #textAplhaNumeric varchar(100)
set #textAplhaNumeric = '1376 schedule items imported from location'
SET #intText = PATINDEX('%[^0-9]%', #textAplhaNumeric)
BEGIN
WHILE #intText > 0
BEGIN
SET #textAplhaNumeric = STUFF(#textAplhaNumeric, #intText, 1, '' )
SET #intText = PATINDEX('%[^0-9]%', #textAplhaNumeric)
END
END
Select #textAplhaNumeric //output is 1376
It will work in case of NULL or empty values.
Please try:
SELECT LEFT(Val,PATINDEX('%[^0-9]%', Val+'a')-1) from(
SELECT
STUFF(ImportCount, 1, PATINDEX('%[0-9]%', ImportCount)-1, '') Val
FROM YourTable
)x