How to split string with delimiter and convert to integer - sql

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))

Related

Is it possible you instatiate a variable in SQL server using a select statement with another variable

I am attempting to DECLARE a variable then SET it's value using a secondary variable which has already had it's value set.
I have tried:
DECLARE #Type VARCHAR = 'Some unique text';
DECLARE #TypeId UNIQUEIDENTIFIER;
SET #TypeId =
(
SELECT Id
FROM Types
WHERE Name = #Type
)
select #TypeId
To no avail. The result of the final SELECT statement is null. The following works:
DECLARE #TypeId UNIQUEIDENTIFIER;
SET #TypeId =
(
SELECT Id
FROM Types
WHERE Name = 'Some unique text'
)
select #TypeId
but I have several tables linked via dependencies and to delete an entry I need to traverse the tables in the correct order pulling the correct Ids. It is likely I will need to do this frequently so I want to reduce the leg work and just enter the text once and the script do the rest.
Is the syntax wrong or is this not possible?
DECLARE #Type VARCHAR = 'Some unique text';
It seems like you try to configure the variable value to be 'Some unique text' but since the type of the variable is VARCHAR(1) then when you set the value the server implicitly CONVERT it to VARCHAR(1) which lead to trunctaing the string and using only the first character
DECLARE #Type VARCHAR = 'Some unique text';
SELECT #Type
GO -- result is "S" and not "Some unique text"
To clarify, using DECLARE #Type VARCHAR without explicitly set the length is translated into 'DECLARE #Type VARCHAR(1)'
As a result of this issue, your comparing of the value probably result with no rows since you compare "S" and not "Some unique text". Your sub query is the same as SELECT Id FROM Types WHERE Name = 'S'
Here is a simple illustration of the issue
------------ DDL+DML: Creating sample table with some data
DROP TABLE IF EXISTS t1, t2
GO
CREATE TABLE t1 (
ID int, [Name] NVARCHAR(100)
)
GO
INSERT t1 (ID, [Name]) Values
(1, 'Mobile '),
(2, 'TV '),
(3, 'Display')
GO
----------- Using VARCHAR without length returns nothing
DECLARE #Type VARCHAR = 'Mobile';
SELECT #Type
DECLARE #TypeId INT;
SET #TypeId =
(
SELECT Id FROM t1 WHERE Name = #Type
)
select #TypeId
----------- Using VARCHAR(100) works great
DECLARE #Type VARCHAR(100) = 'Mobile';
SELECT #Type
DECLARE #TypeId INT;
SET #TypeId =
(
SELECT Id FROM t1 WHERE Name = #Type
)
select #TypeId

Inserting multiple rows through a variable

Actually I want to insert multiple rows to a table.
The Structure of the table is
Create Table tbl_username
(id int autoincrement,
username varchar(100),
Primary key(id))
and I tried to insert multiple rows like
Declare #s as varchar(100)
set #s='(''name1''),(''name2'')'
insert into tbl_username(username)values #s;
but I get the output as
id username
1 (''name1''),(''name2'')
Actually the required output for me is
id username
1 name1
2 name2
How can I achieve this?
Use dynamic SQL
Declare #s as varchar(100)
Declare #sql as varchar(max)
set #s='(''name1''),(''name2'')'
set #sql = 'insert into tbl_username(username) values ' + #s;
execute(#sql);
However I would avoid dynamic SQL where possible.
The standard way to do it if your values are not in a variable is:
INSERT INTO tbl_username(username) values ('name1'),('name2')
Or
INSERT INTO tbl_username(username) values ('name1')
INSERT INTO tbl_username(username) values ('name2')
If possible, opt for one of the above instead of the dynamic option originally mentioned.
insert into tbl_username(username)values ('name1'),('name2'),.....;
Here because username is of type varchar so it's considering #s as single value and inserting it in one row.
The below logic makes use of substring feature:
DECLARE #s as varchar(100), #Delimiter VARCHAR(1)
SET #s = 'name1,name2'
SET #Delimiter = ','
DECLARE #Position INT, #ListItem VARCHAR(MAX)
WHILE CHARINDEX(#Delimiter, #s) > 0
BEGIN
SELECT #Position = CHARINDEX(#Delimiter, #s)
SELECT #ListItem = SUBSTRING(#s, 1, #Position-1)
INSERT INTO tbl_username
SELECT #ListItem
SELECT #s = SUBSTRING(#s, #Position+1, LEN(#s)-#Position)
END
INSERT INTO tbl_username
Select #s
SELECT * FROM tbl_username
Please try: http://sqlfiddle.com/#!6/d0f76/1/0

SQL extracting data from SQL column

I have SQL table JSON data into one of the columns. The column type is varchar max.
I have to extract the data from that column using sql. For example
{"RESPONSE":{"value":"<p>this is a test.....</p>","isAnswered":true}}'
I want to extract: this is a test.....
and get rid of all attributes and Nodes
I am very new to JSON. Fisrt time looking into it and lost
You can try this:
begin transaction
declare #string varchar(max)
declare #result varchar(max)
declare #response varchar(max)
set #string = '{"RESPONSE":{"value":["d"],"isAnswered":true}}'
set #response = SUBSTRING(#string, PATINDEX('%response%',#string), PATINDEX('%":{"value"%',#string) - PATINDEX('%response%',#string))
print #response
-- for html tags
DECLARE #htmlTags TABLE
(
ID INT IDENTITY(1,1),
htmlTag varchar(50)
);
INSERT INTO #htmlTags
VALUES
('<p>'),
('</p>'),
('<h1>'),
('</h1>'),
('"'),
('{'),
('}'),
(':'),
(','),
('value'),
('isAnswered'),
('true'),
('false'),
(' '),
('['),
(']')
;
SET #result = #string
DECLARE #temp varchar(max) = '';
WHILE #result != #temp
BEGIN
SET #temp = #result;
SELECT
#result = Replace(#result, htmlTag, '')
FROM
#htmlTags
;
END;
set #result = REPLACE(#result, #response, '')
print #result
rollback
I'm assuming that the structure of your JSON response is:
{"RESPONSE":{"value":"","isAnswered":true}}
EDIT: I recommend to insert all html tags and names (like ) into the htmlTags table to obtain the result you want since you cannot predict which one of them is going to appear in the json.
UPDATE: use this set #response = SUBSTRING(#string, PATINDEX('%response%',#string), PATINDEX('%":{"value"%',#string) - PATINDEX('%response%',#string)) so you can replace any kind of RESPONSE pattern in your json.
Hope it helps.

Replace " with &quote from varchar variable in 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>

WHERE ... IN ... Issue with the SQL Server Stored Procedure

I have to implement SELECT ... FROM ... WHERE .. IN query in my stored procedure.
Below is the code from my stored procedure
ALTER PROCEDURE [dbo].[SP_GetQuestionSetMultiCat]
-- Add the parameters for the stored procedure here
#PIN varchar(50),
#CatIds varchar(50),
#Range int,
#Que_Type varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare #qtId as int;
select #qtId = Que_Type_Id from dbo.QuestionType_Tbl where Que_Type=#Que_Type;
-- Insert statements for procedure here
Select Top(#Range)
QId,
Que_Type_Id,
Que_Level_Id,
Que_Category_Id,
Que,
Opt1,
Opt2,
Opt3,
Opt4,
Ans
From
dbo.Que_Tbl
Where
(Que_Category_Id in (cast(#CatIds as varchar)))
and (Que_Type_Id=#qtId)
and (Qid not in (Select Que_Id From dbo.UserQuestion_Mapping where PIN=#PIN and Que_typeID=#qtId))
END
Look at the where condition. The Que_Category_Id is int type. What i want to perform is -
Where Que_Category_Id in (1,2,3,4)
The in values i m passing is a string converted from my C# code.
When I am executing this query like -
exec SP_GetQuestionSetMultiCat '666777','4,5,6',5,'Practice'
it is generating an error -
Conversion failed when converting the varchar value '{4,5,6}' to data type int.
Can anybody help me out how to solve this problem.
Thanks for sharing your valuable time.
1)Conversion failed when converting the varchar value '{4,5,6}' to data type int.
The reason of this error is data type precedence. INT data type has "higher" precedence than VARCHAR data type (16-INT vs. 27-VARCHAR).
So, SQL Server is trying to convert '{4,5,6}' to INT and not vice versa.
2) Instead, I would convert #CatIds to XML and then to a table variable (#IDs) using nodes(...) method:
SET ANSI_WARNINGS ON;
DECLARE #CatIds VARCHAR(50) = '4,5,6';
DECLARE #x XML;
SET #x = '<node>' + REPLACE(#CatIds, ',', '</node> <node>') + '</node>';
DECLARE #IDs TABLE
(
ID INT PRIMARY KEY
);
INSERT #IDs(ID)
SELECT t.c.value('.', 'INT')
FROM #x.nodes('/node') t(c);
--Test
SELECT *
FROM #IDs
3) The next step is to rewrite the query using IN (SELECT ID FROM #IDs) instead of in (cast(#CatIds as varchar)):
SET ANSI_WARNINGS ON;
ALTER PROCEDURE [dbo].[SP_GetQuestionSetMultiCat]
-- Add the parameters for the stored procedure here
#PIN varchar(50),
#CatIds varchar(50),
#Range int,
#Que_Type varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare #qtId as int;
select #qtId = Que_Type_Id from dbo.QuestionType_Tbl where Que_Type=#Que_Type;
--Start: New T-SQL code
DECLARE #x XML;
SET #x = '<node>' + REPLACE(#CatIds, ',', '</node> <node>') + '</node>';
DECLARE #IDs TABLE
(
ID INT PRIMARY KEY
);
INSERT #IDs(ID)
SELECT t.c.value('.', 'INT')
FROM #x.nodes('/node') t(c);
--End
-- Insert statements for procedure here
Select Top(#Range)
QId,
Que_Type_Id,
Que_Level_Id,
Que_Category_Id,
Que,
Opt1,
Opt2,
Opt3,
Opt4,
Ans
From
dbo.Que_Tbl
Where
--The search condition is rewritten using IN(subquery)
Que_Category_Id in (SELECT ID FROM #IDs)
and (Que_Type_Id=#qtId)
and (Qid not in (Select Que_Id From dbo.UserQuestion_Mapping where PIN=#PIN and Que_typeID=#qtId))
END
4) Call stored procedure:
exec SP_GetQuestionSetMultiCat '666777','4,5,6',5,'Practice'