Convert textlines in records - sql

I am looking for a way, that I can convert lines of a text in separate records. Perhaps there is someone who has an idea?
I have the following record in a table:
1 blabla Messe\nJahr\nLand
The third field is a textfield. The content is a text with three lines.
now, I should write a select, which gives me as a result three records
1 Memo
2 Jahr
3 Land

i suggest using a cursor and then splitting the string using charpos. as i did not know the name of your table or column, i used table name a, column name a.
declare c cursor for
select a
from a
declare #p varchar(max)
open c
fetch next from c into #p;
while ##FETCH_STATUS = 0
begin
while CHARINDEX('\n',#p,0) > 0
begin
select SUBSTRING(#p,0,charindex('\n',#p,0))
set #p = SUBSTRING(#p,charindex('\n',#p,0)+2, LEN(#p)-charindex('\n',#p,0)-1);
end
select #p;
fetch next from c into #p;
end
DEALLOCATE c
i tested this using
create table a (a varchar(50))
insert into a values ('a\nb\nc')
insert into a values ('d\ne\nf')

use this..
ALTER FUNCTION [dbo].[GetWordsFromString]
(
#string nvarchar(max)
)
RETURNS
#out TABLE
(
Name nvarchar(200)
)
AS
BEGIN
DECLARE #pos int,
#nextpos int,
#valuelen int
SELECT #pos = 0, #nextpos = 1
WHILE #nextpos > 0
BEGIN
SELECT #nextpos = charindex('\', #string, #pos + 1)
SELECT #valuelen = CASE WHEN #nextpos > 0
THEN #nextpos
ELSE len(#string) + 1
END - #pos - 1
INSERT #out
VALUES (convert(nvarchar, substring(#string, #pos + 1, #valuelen)))
SELECT #pos = #nextpos
END
RETURN
END

Related

take minus(-) sign number from sting and use in in different procedure

I have variable
DECLARE #Routs NVARCHAR(1024)
#i int
SET #Routs = N'6,4,-5,8'
I need to extract any number from this sting, where it have minus sign before it (-5 in example)
and use it as input parameter with out (-) sing for example #i in different stored procedure.
Pass in you're #Routs parameter to a table valued function that will split the list into a table and then loop through the table and if the value is a negative number execute stored procedure or whatever you want or do nothing if its not negative.
--table function to split parameter by comma
ALTER FUNCTION [dbo].[SplitListOfInts] (#list nvarchar(MAX))
RETURNS #tbl TABLE (number int NOT NULL) AS
BEGIN
DECLARE #pos int,
#nextpos int,
#valuelen int
if len(rtrim(#list)) > 0
begin
SELECT #pos = 0, #nextpos = 1
WHILE #nextpos > 0
BEGIN
SELECT #nextpos = charindex(',', #list, #pos + 1)
SELECT #valuelen = CASE WHEN #nextpos > 0
THEN #nextpos
ELSE len(#list) + 1
END - #pos - 1
INSERT #tbl (number)
VALUES (convert(int, substring(#list, #pos + 1, #valuelen)))
SELECT #pos = #nextpos
END
end
RETURN
END
-- stored procedure that calls that split function and uses #routs parameter
CREATE TABLE #values(nbrValue int)
INSERT INTO #values(nbrValue
EXEC [dbo].[SplitListOfInts] #routs
--if you don't care about non-negatives delete them here
DELETE FROM #values
where nbrValue >= 0
DECLARE #i int
DECLARE #countrows = (SELECT COUNT(nbrValue) FROM #values)
WHILE #countrows >0
SET #i = (SELECT TOP 1 nbrValue FROM #values)
...do what you want
DELETE FROM #values where nbrValue=#i
set #countrows = (SELECT COUNT(nbrValue) FROM #values)
END

Convert excel data into SQL table

I have a excel which is having some columns (lets say column1, column2, column3, ....so on) and rows, here number of columns and rows are not fixed.
Now data from this excel is copied and inserted into one column (type - nvarchar(max)) of some table...now i have to take data from this column and need to show in tabular format in SQL.
If number of columns had been fixed, i can easily convert column value in xml and show data in tabular format. As number of columns are not fixed, please suggest, how to get desired output.
below is my assumption,
1. you use ',' as delimiter.
2. you not concern about the performance since you insert everything in one column
Will the below helps?
/*create table
CREATE TABLE Tbl ( col nvarchar(max))
insert into Tbl values ('1,2,3,4'),('1,2,3'),('1,2')
***/
DECLARE #maxcol as int,#i as int
SELECT #maxcol=max(LEN(col) - LEN(REPLACE(col, ',', '')))+1 FROM Tbl
select #i=1
declare #nvarsql as nvarchar(max)
select #nvarsql =''
while #i<=#maxcol
begin
set #nvarsql = #nvarsql + ' ISNULL(DBO.fnString_DelimeterIndex(col,'','',' + cast(#i as varchar) +' ),'''') as COL' + CAST(#i AS VARCHAR) + ','
set #i = #i +1
end
if #nvarsql <>''
begin
set #nvarsql = 'SELECT ' + left(#nvarsql,LEN(#nvarsql)-1) + ' FROM Tbl'
end
PRINT #nvarsql
EXEC (#nvarsql)
the Scalar function download from somewhere
ALTER FUNCTION [dbo].[fnString_DelimeterIndex]
(
#Text NVARCHAR(4000),
#Delimiter CHAR,
#Section SMALLINT
)
RETURNS NVARCHAR(4000)
AS
BEGIN
DECLARE #NextPos SMALLINT,
#LastPos SMALLINT,
#Found SMALLINT,
#REVERSE BIT
IF #Section < 0
SELECT #Text = REVERSE(#Text)--, #Section=1,#REVERSE=1
SELECT #NextPos = CHARINDEX(#Delimiter, #Text, 1),
#LastPos = 0,
#Found = 1
WHILE #NextPos > 0 AND ABS(#Section) <> #Found
SELECT #LastPos = #NextPos,
#NextPos = CHARINDEX(#Delimiter, #Text, #NextPos + 1),
#Found = #Found + 1
RETURN CASE
WHEN #Found <> ABS(#Section) OR #Section = 0 THEN NULL
--WHEN #REVERSE =1 THEN
WHEN #Section > 0 THEN SUBSTRING(#Text, #LastPos + 1, CASE WHEN #NextPos = 0 THEN DATALENGTH(#Text) - #LastPos ELSE #NextPos - #LastPos - 1 END)
ELSE REVERSE(SUBSTRING(#Text, #LastPos + 1, CASE WHEN #NextPos = 0 THEN DATALENGTH(#Text) - #LastPos ELSE #NextPos - #LastPos - 1 END))
END
END
results from above sample
COL1 COL2 COL3 COL4
1 2 3 4
1 2 3
1 2

Delete records from table which ids is NOT based on a list of ids (which is nvarchar) separated by comma

I need your help regarding the following situation in SQL Server 2008R2.
In SQL, I have a list of ids saved as NVARCHAR(MAX) like N('1,2,3,4,5')
I read this How to convert comma separated NVARCHAR to table records in SQL Server 2005?
In this scope, I wrote a function for this:
ALTER FUNCTION [dbo].[func$intlist_to_tbl] (#list nvarchar(MAX))
RETURNS #tbl TABLE (number int NOT NULL) AS
BEGIN
DECLARE #pos int,
#nextpos int,
#valuelen int
SELECT #pos = 0, #nextpos = 1
WHILE #nextpos > 0
BEGIN
SELECT #nextpos = charindex(',', #list, #pos + 1)
SELECT #valuelen = CASE WHEN #nextpos > 0
THEN #nextpos
ELSE len(#list) + 1
END - #pos - 1
INSERT #tbl (number)
VALUES (convert(int, substring(#list, #pos + 1, #valuelen)))
SELECT #pos = #nextpos
END
RETURN
END
Ok, I want to delete some records which id IS NOT found in above list.
How to do that ?
I tried something like:
DELETE a_ FROM TableA a_
LEFT JOIN func$intlist_to_tbl(#idList) _tmp
ON _tmp.number = a_.ID_
WHERE a_.ID IS NULL
But is not correct.
Maybe something similar?
DELETE FROM
TableA a_
where
a_.id not in (select number from func$intlist_to_tbl(#idList))

Select * from table where column = (any value from a comma delimited string)

The user selects various words from a drop down list and these values get added into a comma delimited string. When passing the string to a stored procedure I want it to select * from a table where that word exists.
Table
id----word
1-----cat
2-----dog
3-----mouse
4-----dog
string that is passed into the stored procedure is cat, dog so returning columns 1, 2 and 4.
Is there a way of doing this in sql server?
Use IN:
SELECT *
FROM your_table
WHERE word IN ('cat', 'dog')
you first need to make a function SplitCSV :
CREATE FUNCTION [dbo].[SplitCSV] (#CSVString VARCHAR(8000), #Delimiter CHAR(1))
RETURNS #temptable TABLE (items VARCHAR(8000))
AS
BEGIN
DECLARE #pos INT;
DECLARE #slice VARCHAR(8000);
SELECT #pos = 1;
IF LEN(#CSVString) < 1 OR #CSVString IS NULL RETURN;
WHILE #pos!= 0
BEGIN
SET #pos = CHARINDEX(#Delimiter,#CSVString);
IF #pos != 0
SET #slice = LEFT(#CSVString, #pos - 1);
ELSE
SET #slice = #CSVString;
IF( LEN(#slice) > 0)
INSERT INTO #temptable(Items) VALUES (#slice);
SET #CSVString = RIGHT(#CSVString, LEN(#CSVString) - #pos);
IF LEN(#CSVString) = 0 BREAK;
END
RETURN
END
GO
then you can use it like :
SELECT *
FROM myTable
WHERE ID IN (
SELECT items FROM [dbo].[SplitCSV]('1,2,3,4,5', ',')
)
SELECT *
FROM Table
WHERE '%,' + Word + ',%' LIKE ',' + #your_csv_param + ','
Extra commas at the begin and end of parameter and column are to prevent search to match cat with catfish for example.
If you want select all animal except mouse , you can use NOT IN
SELECT * FROM
TABLE
WHERE Word Not IN('Mouse')
So you can avoid type many type of animal
CREATE FUNCTION
ALTER FUNCTION [dbo].[fn_Split](#text varchar(8000), #delimiter varchar(20) = ' ')
RETURNS #Strings TABLE
(
position int IDENTITY PRIMARY KEY,
value varchar(8000)
)
AS
BEGIN
DECLARE #index int
SET #index = -1
WHILE (LEN(#text) > 0)
BEGIN
SET #index = CHARINDEX(#delimiter , #text)
IF (#index = 0) AND (LEN(#text) > 0)
BEGIN
INSERT INTO #Strings VALUES (#text)
BREAK
END
IF (#index > 1)
BEGIN
INSERT INTO #Strings VALUES (LEFT(#text, #index - 1))
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
ELSE
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
RETURN
END
----
select * from yourtable where column in ( select value from fn_Split(#para1,',')

How to generate spaces between letters in Sql Server 2005 (Set Based)

Input
Column
ab2e
mnop
a2t1y
output
Id Col1 Col2 Col3 Col4 Col5 Col6
1 a b e
2 m n o p
3 a t y
The numbers indicates the number of spaces
Since in the first input, there is 2 after b, so the letter e will appear after 2 spaces from b.
In the second input since there is no space, the the letters will appear after each other
Thanks
If you've already got a way of distributing a 'normal' string's contents between the columns and only need a solution for expanding strings like ab2e into strings like ab[space][space]e, then here's a possible solution:
DECLARE #InputString varchar(100), #pos int, #result varchar(100);
SET #InputString = 'a2t1y';
SET #result = #InputString;
SET #pos = PATINDEX('%[0-9]%', #result);
WHILE #pos <> 0 BEGIN
SET #result = STUFF(#result, #pos, 1, SPACE(SUBSTRING(#result, #pos, 1)));
SET #pos = PATINDEX('%[0-9]%', #result);
END
SELECT #result;
The output:
---------------------
a t y
It would probably be a nice idea to implement it as a function:
CREATE FUNCTION ExpandString (#String varchar(100))
RETURNS varchar(100)
AS BEGIN
DECLARE #pos int, #result varchar(100);
SET #result = #String;
SET #pos = PATINDEX('%[0-9]%', #result);
WHILE #pos <> 0 BEGIN
SET #result = STUFF(#result, #pos, 1, SPACE(SUBSTRING(#result, #pos, 1)));
SET #pos = PATINDEX('%[0-9]%', #result);
END
RETURN #result;
END
so you could call it on a column like this:
SELECT …, dbo.ExpandString(t.SomeColumn), …
It should be noted, though, that this solution only supports single-digit 'macros', i.e. a12b would be converted to a[1 space][2 spaces]b with this function, which is not necessarily what you'd expect. So, if you need it to recognise integers as sequences of numeric characters between non-numerics, here's an alternative solution:
CREATE FUNCTION ExpandString (#String varchar(100))
RETURNS varchar(100)
AS BEGIN
DECLARE #pos int, #lastpos int, #len int, #isnum bit,
#sub varchar(100), #result varchar(100);
SET #result = '';
SET #pos = 1;
SET #len = LEN(#String);
SET #isnum = ISNUMERIC(SUBSTRING(#String, #pos, 1));
WHILE #pos <= #len BEGIN
SET #lastpos = #pos;
WHILE #pos <= #len AND ISNUMERIC(SUBSTRING(#String, #pos, 1)) = #isnum
SET #pos = #pos + 1;
SET #sub = SUBSTRING(#String, #lastpos, #pos - #lastpos);
SET #result = #result + CASE #isnum WHEN 1 THEN SPACE(#sub) ELSE #sub END;
SET #isnum = #isnum ^ 1;
END;
RETURN #result;
END
Both versions recognise numbers both at the beginning and at the end of the input string.