I want to do the following using SQL Server 2005.
Create a stored procedure that takes a varchar() comma "," delimited param
Split / Explode the varchar() param and insert the values in a temporary table
Something that will do the following:
INSERT INTO #temp_table SPLIT('john,peter,sally',',');
SELECT * FROM #temp_table;
Is there a function or stored procedure that will perform a split?
If so, how does it work?
Thanks
SQL Server does not have a string split function out of the box, but you can create one like this
CREATE FUNCTION dbo.Split(#String varchar(8000), #Delimiter char(1))
returns #temptable TABLE (items varchar(8000))
as
begin
declare #idx int
declare #slice varchar(8000)
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
insert into #temptable(Items) values(#slice)
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end
Related
I have metadata stored in a key/value table in SQL Server. I know this is bad way of storing the data but we couldn't avoid it. Users need to be able to give me an arbitrary set of key/value pairs and have me return the Template id that match their criteria. My application is a Spring boot with JPA enabled.
Below is how it is saved in DB. Multiple Contexts differentiate a template
Would like to know how does my repository method should be designed to get the correct Template id.
Have tried different ways but always getting both the templates for any data provided. Example like below I need to get only template 3
{
"Role":"PMGR",
"Country":"IN",
"Unit":"000737",
"Test":"VALUE2"
}
I would like to know the best way of doing this
first create this split function
create FUNCTION [dbo].[Split](#String varchar(8000),#Delimiter char(1))
returns #temptable TABLE (k varchar(8000),v varchar(8000))
as
begin
declare #idx int
declare #slice varchar(8000)
declare #c int;
set #c=0;
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
begin
declare #k varchar(8000) =substring(#slice,2,charindex(':',#slice)-3)
declare #v varchar(8000) =reverse(substring(reverse(#slice),2,charindex(':',reverse(#slice))-3))
insert into #temptable(k,v )
values(ltrim(rtrim(replace(#k,'"',''))),ltrim(rtrim(#v)))
set #c=#c+1;
end
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end
Then use this query
declare #param nvarchar(max)='"Role":"PMGR",
"Country":"IN",
"Unit":"000737",
"Test":"VALUE2"'
select t2.k,t2.v,t2.id from
[dbo].[Split](REPLACE(REPLACE(REPLACE(#param, CHAR(9), ''), CHAR(10), ''), CHAR(13), ''),',') as t1 -- re
inner join t2 -- your table
on t1.k=t2.k
and t1.v=t2.v
/*
CHAR(9) - Tab
CHAR(10) - New Line
CHAR(13) - Carriage Return
*/
If I have a value something like '10,10,20,30,40,20' in a field of table, then I want to make it as '10,20,30,40'
Is there any sql function to do such thing?
Thanks
Sudhakar
using Jeff's DelimitedSplit8K from http://www.sqlservercentral.com/articles/Tally+Table/72993/
declare #value varchar(100) = '10,10,20,30,40,20',
#new_value varchar(100)
select #new_value = isnull(#new_value + ',', '') + Item
from DelimitedSplit8K(#value, ',')
group by Item
order by Item
select #new_value
Did this long ago. This might need some modifications. But it generates output.
Try :
DECLARE #Data_String AS VARCHAR(1000), #Result as varchar(1000)=''
SET #Data_String = '10,10,20,30,40,20'
SET #Data_String = REPLACE(#Data_String,'|',',')
select #Data_String;
SELECT #Result=#Result+col+',' from(
SELECT DISTINCT t.c.value('.','varchar(100)') col from(
SELECT cast('<A>'+replace(#Data_String,',','</A><A>')+'</A>' as xml)col1)data
cross apply col1.nodes('/A') as t(c))Data
SELECT LEFT(#Result,LEN(#Result)-1)
believing it stores integer number you can get them with creating a function first you need to split the values then have to use a distinct function as below
1st create a function like
CREATE FUNCTION [dbo].[idpGetSplitedString]
(
#String varchar(8000),
#Delimiter char(1)
)
RETURNS
#temptable TABLE
(
items varchar(8000)
)
AS
BEGIN
declare #idx int
declare #slice varchar(8000)
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
insert into #temptable(Items) values(rtrim(ltrim(#slice)))
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
RETURN
END
then call the function like
select [dbo].idpGetSplitedString as Values
Sorry all details are in the Image stuggling to get the text on
Please advise me on this
Regard Lee'Roy
Here is my split function:
CREATE FUNCTION [dbo].[Split](#String varchar(8000), #Delimiter char(1))
returns #temptable TABLE (items varchar(8000))
as
begin
declare #idx int
declare #slice varchar(8000)
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
insert into #temptable(Items) values(#slice)
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end
As mentioned in the comments to your question, you will need to create a function that splits your text values and returns a table for you to join on.
There are numerous ways to do this and most of them would be far too involved to include in this Q&A format*. The best write up you will probably get is from Jeff Moden.
* Which I know is slightly against the rules on answers here, but googling "String split function SQL Server" will get you something useful should the link above die
This question already has answers here:
Parameterize an SQL IN clause
(41 answers)
Closed 7 years ago.
I can do this and it works (but would like something more simple):
Declare #PropIDs varchar(50)
Set #PropIDs = '1, 2'
IF OBJECT_ID('dbo.TempProp') IS NOT NULL DROP TABLE dbo.TempProp
CREATE TABLE [dbo].[TempProp](
[PropCode] [VarChar](3) NULL)
Set #Sql = 'Insert Into TempProp Select PropertyCode From Property where PropertyID In (' + #PropIDs + ')'
Execute (#Sql)
But I wish I could do just this:
Declare #PropIDs
Set #PropIDs = '1, 2'
Select PropertyCode
Into #TempProp
From Property where PropertyID IN (#PropIDs)
It is the "...Property IN (#PropIDs)" that is giving me trouble.
Any suggestions?
Create a split table value function similar to this one
create FUNCTION [dbo].[Split](#String varchar(MAX), #Delimiter char(1))
returns #temptable TABLE (items varchar(MAX))
as
begin
declare #idx int
declare #slice varchar(8000)
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
insert into #temptable(Items) values(#slice)
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end;
That code is from this question: separate comma separated values and store in table in sql server
Then use it in your query like this:
Declare #PropIDs
Set #PropIDs = '1, 2'
Select PropertyCode
Into #TempProp
From Property where PropertyID IN (dbo.Slit(#PropIDs, ','))
My stored procedure:
ALTER PROCEDURE [dbo].[Perdate]
#D_Data as nvarchar(999)
AS
SELECT 'Total'= SUM(CAST(TBL_Stock.R_TotalPrice as decimal(18,2))),(convert(varchar,TBL_Stock.D_Datepush,105)) as Date
FROM TBL_Stock
GROUP BY (convert(varchar,TBL_Stock.D_Datepush,105))
Having (convert(varchar,TBL_Stock.D_Datepush,105)) = #D_Data
I would like to know if it is possible to set that variable (#D_Data) as something like:
'02-03-2012' or (convert(varchar,TBL_Stock.D_Datepush,105)) = '02-04-2012'
So the having clause would be :
HAVING (convert(varchar, TBL_Stock.D_Datepush, 105)) = '02-03-2012'
OR (convert(varchar, TBL_Stock.D_Datepush, 105)) = '02-04-2012'
So my idea is to have (in my VB.net project) a string that could dynamically change the stored procedure "Future"
Seems like you want to do SQL injection so that your input param "glues into" the TSQL that is being built in your proc. THIS IS A VERY BAD IDEA ( see SQL Injection discussion here).
But good news, dynamic SQL is not needed. Use a table function to parse the incoming string so that it can be joined in the proc.
create table TBL_Stock(R_TotalPrice decimal(18,2), D_Datepush datetime)
insert into TBL_Stock(R_TotalPrice,D_datepush) values(1000,'1/1/2012')
insert into TBL_Stock(R_TotalPrice,D_datepush) values(200,'1/2/2012')
insert into TBL_Stock(R_TotalPrice,D_datepush) values(30,'1/3/2012')
insert into TBL_Stock(R_TotalPrice,D_datepush) values(4,'1/4/2012')
GO
CREATE FUNCTION dbo.SplitDates(#String varchar(8000), #Delimiter char(1))
returns #temptable TABLE (dt datetime)
as
begin
declare #idx int
declare #slice varchar(8000)
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0 AND isDate(#slice) = 1)
insert into #temptable(dt) values(#slice)
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end
GO
--test function
select * from dbo.SplitDates('1/1/2012,1/2/2012',',')
GO
create PROCEDURE Perdate #D_Data as nvarchar(2000)
AS
select
PushDate=z.dt,
'Total'= SUM(s.R_TotalPrice)
from
dbo.splitDates(#D_Data,',') z
join TBL_Stock s on s.D_datepush = z.dt
group by
z.dt
GO
--Test proc
select * from TBL_Stock
exec Perdate '1/1/2012'
exec Perdate '1/1/2012,1/2/2012'
exec Perdate '1/1/2012,1/4/12'