Replace " with &quote from varchar variable in sql - sql

I'm trying to replace " with &quot, replace(#variable,'"','"') didn't help, in XML I got
<tag>&amp quot;Test&amp quot;</tag>
instead of
<tag>"test"</tag>
Example:
DECLARE #Text varchar(20) = '"Test"'
SET #Text = REPLACE(#Text,'"','&quot ;')
SELECT #Text
DECLARE #Table table (ID int)
INSERT INTO #Table
(ID)
VALUES
(123)
DECLARE #TestXml AS XML = (
SELECT
#Text
FROM #Table AS tag
FOR XML AUTO, ELEMENTS
)
SELECT #TestXml
Thanks in advance

if the problem is in the select query, try below sql
change the
SELECT #TestXml
to
SELECT '<tag>' + #TestXml.value('/tag[1]','varchar(max)') + '</tag>' as 'Word'
you will get below result in the select query:
Word
-------------------------------
<tag>"Test"</tag>
Update
to keep the '&' char we need the <![CDATA[...]>
try below sql
Declare #text nvarchar(20) = '"Test"'
select #text = replace(#text,'"','"')
Declare #table table (ID int)
Declare #xml as nvarchar(Max)
insert into #table values (123)
set #xml=( Select
1 as tag,
Null as Parent,
#text as [tag!1!!CDATA]
from #table
for xml Explicit
)
select #xml
Result:
result
---------------------------------------
<tag><![CDATA["Test"]]></tag>

Related

Convert a column value into series of rows and columns in SQL [duplicate]

This question already has answers here:
Parsing a string SQL
(3 answers)
Closed 8 years ago.
I have a table in which one column is having data like as below:
column value='A,B,C,D,E,F
XA123,Name1,10/20,1.11,27-03-2014,414BJE
XA154,Name2,10/10,1.143,26-03-2014,414B32
XA134,Name21,10/50,1.123,27-03-2014,414B534E
XA125,Name32,20/20,1.1234,17-02-2014,414BJ3
XA124,Name43,30/20,1.165,23-02-2014,414B432
XA1256,Name324,50/60,4.31,07-01-2014,4GHH
XA1252,Name32,70/60,6.61,09-12-2013,414B2E'
Now i need this column value to be sorted out like that in a separate table.
Expected Output:
A B C D E F
XA123 Name1 10/20 1.11 27-03-2014 414BJE
XA154 Name2 10/10 1.143 26-03-2014 414B32
XA134 Name21 10/50 1.123 27-03-2014 414B534E
XA125 Name32 20/20 1.1234 17-02-2014 414BJ3
XA124 Name43 30/20 1.165 23-02-2014 414B432
XA1256 Name324 50/60 4.31 07-01-2014 4GHH
XA1252 Name32 70/60 6.61 09-12-2013 414B2E
Edit:
To get the above solution, at first, i divided column value based on new line character and inserted into a new table variable:
Declare #value nvarchar(max) ='A,B,C,D,E,F
XA123,Name1,10/20,1.11,27-03-2014,414BJE
XA154,Name2,10/10,1.143,26-03-2014,414B32
XA134,Name21,10/50,1.123,27-03-2014,414B534E
XA125,Name32,20/20,1.1234,17-02-2014,414BJ3
XA124,Name43,30/20,1.165,23-02-2014,414B432
XA1256,Name324,50/60,4.31,07-01-2014,4GHH
XA1252,Name32,70/60,6.61,09-12-2013,414B2E'
Declare #t Table
(
Id int identity(1,1),
Val VARCHAR(max)
)
while (charindex(char(13),#value)>0)
BEGIN
insert into #t (Val)
select substring(#value,1,charindex(char(13),#value))
set #value = (select substring(#value,charindex(char(13),#value)+1,len(#value)))
END
select * from #t
Then i created a new table variable and separated value for each row of #t table variable based on ','. Now hoping to get a generic and better solution.
Edited again:
Here I am trying to make a generic solution for this issue..lets say values in these rows can go to any number, for ex:
A,B,C,D,E,F could be
A,B,C,D,E,F,G
A,B,C,D,E,F,G,H
A,B,C,D,E,F,G,H....Z
so i am trying to get solution using dynamic query in below code, but getting an error: Must declare the scalar variable "#xml"
Declare #value nvarchar(max) ='A,B,C,D,E,F,G
XA123,Name1,10/20,1.11,27-03-2014,414BJE,afs
XA154,Name2,10/10,1.143,26-03-2014,414B32,ag
XA134,Name21,10/50,1.123,27-03-2014,414B534E,GSF
XA125,Name32,20/20,1.1234,17-02-2014,414BJ3,GG
XA124,Name43,30/20,1.165,23-02-2014,414B432,GS
XA1256,Name324,50/60,4.31,07-01-2014,4GHH,GS
XA1252,Name32,70/60,6.61,09-12-2013,414B2E,sg'
declare #query varchar(max)
declare #xml xml
declare #count int
declare #i int = 1
select #xml = '<item><value>'+replace(replace(#value, ',','</value><value>'), char(10),'</value></item><item><value>')+'</value></item>'
DECLARE #XmlTable TABLE (XmlResult XML)
INSERT INTO #XmlTable select #xml
set #count = (SELECT XmlResult.value('count(/item/value)', 'int')/XmlResult.value('count(/item)', 'int') FROM #XmlTable)
SET #query = 'select '
WHILE (#i <= #count)
BEGIN
IF(#i!=1)
BEGIN
set #query = #query + ', '
END
set #query = #query + 'N.value(''substring(value['+ cast(#i as varchar) +'],1)'',''varchar(10)'')'
SET #i = #i + 1
END
set #query = #query + ' from ' + '#xml.nodes' + '(''item'') as T(N)'
-- select #query
EXEC(#query)
Guys, any suggestion...
Here it is...
Declare #value nvarchar(max) ='A,B,C,D,E,F
XA123,Name1,10/20,1.11,27-03-2014,414BJE
XA154,Name2,10/10,1.143,26-03-2014,414B32
XA134,Name21,10/50,1.123,27-03-2014,414B534E
XA125,Name32,20/20,1.1234,17-02-2014,414BJ3
XA124,Name43,30/20,1.165,23-02-2014,414B432
XA1256,Name324,50/60,4.31,07-01-2014,4GHH
XA1252,Name32,70/60,6.61,09-12-2013,414B2E'
declare #xml xml
select #xml = '<item><value>'+replace(replace(#value, ',','</value><value>'), char(13),'</value></item><item><value>')+'</value></item>'
select
N.value('substring(value[1],1)', 'varchar(10)') as V1,
N.value('substring(value[2],1)', 'varchar(10)') as V2,
N.value('substring(value[3],1)', 'varchar(10)') as V3,
N.value('substring(value[4],1)', 'varchar(10)') as V4,
N.value('substring(value[5],1)', 'varchar(10)') as V5,
N.value('substring(value[6],1)', 'varchar(10)') as V6
from #xml.nodes('item') as T(N)
Try this, First Create a Scalar function AS
Create FUNCTION [dbo].[funcSplit_OneVal]
(
#param NVARCHAR(MAX),
#delimiter CHAR(1),
#nThVal int
)
RETURNS varchar(50)
--select dbo.funcSplit_OneVal('1,2,3,4',',',5)
AS
BEGIN
Declare #t TABLE (val NVARCHAR(MAX))
Declare #retVal varchar(50) = ''
SET #param += #delimiter
;WITH a AS
(
SELECT CAST(1 AS BIGINT) f,
CHARINDEX(#delimiter, #param) t,
1 seq
UNION ALL
SELECT t + 1,
CHARINDEX(#delimiter, #param, t + 1),
seq + 1
FROM a
WHERE CHARINDEX(#delimiter, #param, t + 1) > 0
)
INSERT #t
SELECT SUBSTRING(#param, f, t - f)
FROM a
OPTION(MAXRECURSION 0)
select top (#nThVal) #retVal =val from #t
RETURN #retVal
END
Then Execute following Script,
Declare #value nvarchar(max) ='A,B,C,D,E,F
XA123,Name1,10/20,1.11,27-03-2014,414BJE
XA154,Name2,10/10,1.143,26-03-2014,414B32
XA134,Name21,10/50,1.123,27-03-2014,414B534E
XA125,Name32,20/20,1.1234,17-02-2014,414BJ3
XA124,Name43,30/20,1.165,23-02-2014,414B432
XA1256,Name324,50/60,4.31,07-01-2014,4GHH
XA1252,Name32,70/60,6.61,09-12-2013,414B2E'
DECLARE #xml AS XML = CAST(('<X>'+REPLACE(#value,' ' ,'</X><X>')+'</X>') AS XML)
;With CTE as
(
SELECT C.value('.', 'varchar(250)') AS value
FROM #xml.nodes('X') as X(C)
)
select dbo.funcSplit_OneVal(value,',',1)
,dbo.funcSplit_OneVal(value,',',2)
,dbo.funcSplit_OneVal(value,',',3)
,dbo.funcSplit_OneVal(value,',',4)
,dbo.funcSplit_OneVal(value,',',5)
,dbo.funcSplit_OneVal(value,',',6)
from CTE
where len(value) > 0
If required then you can remove 'A,B,C... from variable & give alise in Last Select.

How to split string with delimiter and convert to integer

hi i am writing query in sql server procedure in which i pass comma seprated nvarchar values i want to filter these value in sql server query code is given below
declare #RoleId NVARCHAR(MAX) = '1,2,3'
Declare #RoleTempId int;
Set #RoleTempId = Cast(#RoleId As INT);
BEGIN
SELECT dbo.RolePermission.PermissionId, dbo.Permission.PermissionName
FROM dbo.RolePermission INNER JOIN
dbo.Permission ON dbo.RolePermission.PermissionId = dbo.Permission.PermissionId
WHERE (dbo.RolePermission.RoleId IN (#RoleTempId))
END
this is giving error please guide me about this query thank you.
One simple solution for string splitting is to convert the source (1,2,3) string (which could be declared as VARCHAR and not NVARCHAR if it contains only integers) to XML (<r>1</r><r>2</r><r>3</r>) and then you could shredd this XML and insert every values (integer) into a table variable:
DECLARE #RoleId NVARCHAR(MAX) = '1,2,3'
DECLARE #SelectedRoles TABLE (RoleId INT PRIMARY KEY); -- No duplicates allowed
DECLARE #x XML;
SET #x = N'<r>' + REPLACE((SELECT #RoleId FOR XML PATH('')), N',', N'</r><r>') + N'</r>';
/*
#x content:
<r>1</r><r>2</r><r>3</r>
*/
INSERT #SelectedRoles (RoleId)
SELECT y.XmlCol.value('(.)', 'INT') AS RoleId
FROM #x.nodes('/r') y(XmlCol);
...
WHERE (dbo.RolePermission.RoleId IN (SELECT sr.RoleId FROM #SelectedRoles sr))

SQL Variable in XML Node

I have the following code:
DECLARE #x TABLE (item XML (document Galeries))
DECLARE #schemaname VARCHAR(100)
SET #schemaname = 'GaleriesSchem2'
INSERT into #x
SELECT '
<GaleriesSchem2>
<Image_1 OriginalName="Image">4814111.jpg</Image_1>
<Image_2 OriginalName="Image2">481411.jpg</Image_2>
</GaleriesSchem2>'
SELECT rref.value('.', 'varchar(MAX)') AS 'Value'
FROM #x
CROSS APPLY
item.nodes('//GaleriesSchem2/node()') AS Results(rref)
result:
1 | 4814111.jpg
2 | 481411.jpg
But I want to change the root element dynamically, for example:
item.nodes('//[local-name()=sql:variable("#schemaname")]/node()') AS Results(rref)
But this code doesn't work.
Use asterisk instead of double slash
DECLARE #x TABLE(item XML)
DECLARE #schemaname VARCHAR(100)
SET #schemaname = 'GaleriesSchem3'
INSERT into #x
SELECT '
<GaleriesSchem2>
<Image_1 OriginalName="Image">4814111.jpg</Image_1>
<Image_2 OriginalName="Image2">481411.jpg</Image_2>
</GaleriesSchem2>
<GaleriesSchem3>
<Image_1 OriginalName="Image">4814111_3.jpg</Image_1>
<Image_2 OriginalName="Image2">481411_3.jpg</Image_2>
</GaleriesSchem3>
'
SELECT rref.value('.', 'varchar(MAX)') AS 'Value'
FROM #x
CROSS APPLY
item.nodes('*[local-name()=sql:variable("#schemaname")]/node()') AS Results(rref)
See demo on SQLFiddle

How to convert comma separated NVARCHAR to table records in SQL Server 2005?

I have a list of ids separated by comma like:
1,17,25,44,46,67,88
I want to convert them to a table records ( into a temporary table ) like
#tempTable
number_
--------
1
17
25
44
46
67
88
It is possible with a function, a table-valued one ?
Why I want this ? I want to use for INNER JOIN clause (into stored procedure) with another table(s) like as:
SELECT a,b,c FROM T1
INNER JOIN functionNameWhichReturnsTable
ON functionNameWhichReturnsTable.number_ = T1.a
I cannot use IN because I will use stored procedure which accepts a parameter of type NVARCHAR. That parameter will provide the list of ids.
Thank you
Possible duplicate of separate comma separated values and store in table in sql server.
Please try a precise one from Comma-Delimited Value to Table:
CREATE FUNCTION [dbo].[ufn_CSVToTable] ( #StringInput VARCHAR(8000), #Delimiter nvarchar(1))
RETURNS #OutputTable TABLE ( [String] VARCHAR(10) )
AS
BEGIN
DECLARE #String VARCHAR(10)
WHILE LEN(#StringInput) > 0
BEGIN
SET #String = LEFT(#StringInput,
ISNULL(NULLIF(CHARINDEX(#Delimiter, #StringInput) - 1, -1),
LEN(#StringInput)))
SET #StringInput = SUBSTRING(#StringInput,
ISNULL(NULLIF(CHARINDEX(#Delimiter, #StringInput), 0),
LEN(#StringInput)) + 1, LEN(#StringInput))
INSERT INTO #OutputTable ( [String] )
VALUES ( #String )
END
RETURN
END
GO
Check the requirement in other way using XML:
DECLARE #param NVARCHAR(MAX)
SET #param = '1:0,2:1,3:1,4:0'
SELECT
Split.a.value('.', 'VARCHAR(100)') AS CVS
FROM
(
SELECT CAST ('<M>' + REPLACE(#param, ',', '</M><M>') + '</M>' AS XML) AS CVS
) AS A CROSS APPLY CVS.nodes ('/M') AS Split(a)
Here's a trick that doesn't need a function or XML.
Basically the string gets transformed into a single insert statement for a temporary table.
The temp table can then be used for further processing.
IF OBJECT_ID('tempdb..#tmpNum') IS NOT NULL
DROP TABLE #tmpNum;
CREATE TABLE #tmpNum (num int);
DECLARE #TEXT varchar(max) = '1,17,25,44,46,67,88';
DECLARE #InsertStatement varchar(max);
SET #InsertStatement = 'insert into #tmpNum (num) values ('+REPLACE(#TEXT,',','),(')+');';
EXEC (#InsertStatement);
-- use the temp table
SELECT *
FROM YourTable t
WHERE t.id IN (SELECT DISTINCT num FROM #tmpNum);
This method is usable for up to 1000 values.
Because 1000 is the max limit of a row value expression.
Also, as Stuart Ainsworth pointed out.
Since this method uses Dynamic Sql, be wary of code injection and don't use it for strings based on user input.
Side-note
Starting from MS Sql Server 2016, one could simply use the STRING_SPLIT function.
DECLARE #TEXT varchar(max);
SET #TEXT = '1,17,25,44,46,67,88';
SELECT t.*
FROM YourTable t
JOIN (SELECT DISTINCT CAST(value AS INT) num FROM STRING_SPLIT(#TEXT, ',')) nums
ON t.id = nums.num;
Completing the answers, you could also use the CSV string to store multiple values in multiple columns:
--input sql text
declare #text_IN varchar(max) ='text1, text1.2, text1.3, 1, 2010-01-01\r\n text2, text2.2, text2.3, 2, 2016-01-01'
Split the csv file into rows:
declare #temptable table (csvRow varchar(max))
declare #DelimiterInit varchar(4) = '\r\n'
declare #Delimiter varchar(1) = '|'
declare #idx int
declare #slice varchar(max)
set #text_IN = REPLACE(#text_IN,#DelimiterInit,#Delimiter)
select #idx = 1
if len(#text_IN)<1 or #text_IN is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#text_IN)
if #idx!=0
set #slice = left(#text_IN,#idx - 1)
else
set #slice = #text_IN
if(len(#slice)>0)
insert into #temptable(csvRow) values(#slice)
set #text_IN = right(#text_IN,len(#text_IN) - #idx)
if len(#text_IN) = 0 break
end
Split rows into columns:
;WITH XMLTable (xmlTag)
AS
(
SELECT CONVERT(XML,'<CSV><champ>' + REPLACE(csvRow,',', '</champ><champ>') + '</champ></CSV>') AS xmlTag
FROM #temptable
)
SELECT RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[1]','varchar(max)'))) AS Column1,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[2]','varchar(max)'))) AS Column2,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[3]','varchar(max)'))) AS Column3,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[4]','int'))) AS Column4,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[5]','datetime'))) AS Column5
FROM XMLTable
The following works:
declare #parStoreNo As varchar(8000) = '1,2,3,4'
CREATE TABLE #parStoreNo (StoreNo INT)-- drop #parStoreNo
declare #temptable VARCHAR(1000) = #parStoreNo
declare #SQL VARCHAR(1000)
SELECT #SQL = CONVERT(VARCHAR(1000),' select ' + REPLACE(ISNULL(#temptable,' NULL '),',', ' AS Col UNION ALL SELECT '))
INSERT #parStoreNo (StoreNo)
EXEC (#SQL)
I am using XML Function as below...
DECLARE #str VARCHAR(4000) = '6,7,7,8,10,12,13,14,16,44,46,47,394,396,417,488,714,717,718,719,722,725,811,818,832,833,836,837,846,913,914,919,922,923,924,925,926,927,927,928,929,929,930,931,932,934,935,1029,1072,1187,1188,1192,1196,1197,1199,1199,1199,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1366,1367,1387,1388,1666,1759,1870,2042,2045,2163,2261,2374,2445,2550,2676,2879,2880,2881,2892,2893,2894'
Declare #x XML
select #x = cast('<A>'+ replace(#str,',','</A><A>')+ '</A>' as xml)
select t.value('.', 'int') as inVal
from #x.nodes('/A') as x(t)
I prefer this because not need to create any separate function and proc. Also I don't have to opt dynamic SQL query which I prefer most.
Convert Comma Separated String to Table
DECLARE #str VARCHAR(4000) = '6,7,7,8,10,12,13,14,16,44,46,47,394,396,417,488,714,717,718,719,722,725,811,818,832'
DECLARE #x XML
select #x = cast('<A>'+ replace(#str,',','</A><A>')+ '</A>' as xml)
select t.value('.', 'int') as inVal
from #x.nodes('/A') as x(t)
Try this code
SELECT RTRIM(part) as part
INTO Table_Name
FROM dbo.splitstring(#Your_Comma_string,',')
splitstring Function is as follows
CREATE FUNCTION dbo.splitstring ( #stringToSplit VARCHAR(MAX) )
RETURNS
#returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN
DECLARE #name NVARCHAR(255)
DECLARE #pos INT
WHILE CHARINDEX(',', #stringToSplit) > 0
BEGIN
SELECT #pos = CHARINDEX(',', #stringToSplit)
SELECT #name = SUBSTRING(#stringToSplit, 1, #pos-1)
INSERT INTO #returnList
SELECT #name
SELECT #stringToSplit = SUBSTRING(#stringToSplit, #pos+1, LEN(#stringToSplit)-#pos)
END
INSERT INTO #returnList
SELECT #stringToSplit
RETURN
END

Insert multiple rows into temp table with one command in SQL2005

I've got some data in the following format:
-1,-1,-1,-1,701,-1,-1,-1,-1,-1,304,390,403,435,438,439,442,455
I need to insert it into a temp table like this:
CREATE TABLE #TEMP
(
Node int
)
So that I can use it in a comparison with data in another table.
The data above represents separate rows of the "Node" column.
Is there an easy way to insert this data, all in one command?
Also, the data will actually being coming in as seen, as a string... so I need to be able to just concat it into the SQL query string. I can obviously modify it first if needed.
Try something like
CREATE TABLE #TEMP
(
Node int
)
DECLARE #textXML XML
DECLARE #data NVARCHAR(MAX),
#delimiter NVARCHAR(5)
SELECT #data = '-1,-1,-1,-1,701,-1,-1,-1,-1,-1,304,390,403,435,438,439,442,455 ',
#delimiter = ','
SELECT #textXML = CAST('<d>' + REPLACE(#data, #delimiter, '</d><d>') + '</d>' AS XML)
INSERT INTO #TEMP
SELECT T.split.value('.', 'nvarchar(max)') AS data
FROM #textXML.nodes('/d') T(split)
SELECT * FROM #TEMP
DROP TABLE #TEMP
You can create a query dynamically like this:
declare #sql varchar(1000)
set #sql = 'insert into #TEMP select ' + replace(#values, ',', ' union all select ')
exec #sql
As always when creating queries dynamically, you have to be careful so that you only use trusted data.
I would create a function that would return a table variable and then join that function into the select
Use:
select * from myTable a
inner join dbo.buildTableFromCSV('1,2,3') on a.id = b.theData
Here is my function for doing this
CREATE FUNCTION [dbo].[buildTableFromCSV] ( #csvString varchar(8000) ) RETURNS #myTable TABLE (ID int identity (1,1), theData varchar(100))
AS BEGIN
DECLARE #startPos Int -- position to chop next block of chars from
DECLARE #currentPos Int -- position to current character we're examining
DECLARE #strLen Int
DECLARE #c char(1) -- current subString
-- variable initalization
-- -------------------------------------------------------------------------------------------------------------------------------------------------
SELECT #csvString = #csvString + ','
SELECT #startPos = 1
SELECT #currentPos = 1
SELECT #strLen = Len(#csvString)
-- loop over string and build temp table
-- -------------------------------------------------------------------------------------------------------------------------------------------------
WHILE #currentPos <= #strLen BEGIN
SET #c = SUBSTRING(#csvString, #currentPos, 1 )
IF ( #c = ',' ) BEGIN
IF ( #currentPos - #startPos > 0 ) BEGIN
INSERT
INTO #myTable ( theData )
VALUES ( CAST( SUBSTRING ( #csvString, #startPos, #currentPos - #startPos) AS varchar ) )
END
ELSE
begin
INSERT
INTO #myTable ( theData )
VALUES ( null )
end
SELECT #startPos = #currentPos + 1
END
SET #currentPos = #currentPos + 1
END
delete from #myTable where theData is null
return
END