When I run my first query, I get 5 rows of result. The value for row1 is "Day1", row 2 is "Day2" and etc... After that I want combine it to a string as "Day1,Day2,Day3,Day4,Day5". But after I run the stored procedure, I get empty result. Below is my stored procedure. How to I solve it? Thanks
SET NOCOUNT ON
Declare #PeriodID nvarchar(50);
Declare #FinalString nvarchar(80);
DECLARE vendor_cursor CURSOR FOR
SELECT PeriodID FROM PeriodTable c WHERE c.Active=1
OPEN vendor_cursor
FETCH NEXT FROM vendor_cursor
INTO #PeriodID
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #FinalString = #FinalString + #PeriodID + ','
FETCH NEXT FROM vendor_cursor
INTO #PeriodID
END
CLOSE vendor_cursor;
DEALLOCATE vendor_cursor;
print #FinalString
SET NOCOUNT OFF
No need for a cursor. I think you missed setting the variable to a blank string first so it was null making each row null. This works:
declare #ret varchar(8000)
set #ret = ''
select #ret = #ret+', '+name
from ImagedApps
order by name
-- take off the first comma and space
select substring(#ret, 3, 8000)
Related
I would like to have a multiple values Paramter with text1, text2, text3
SSRS should only show me the rows that contain one or all of this Parameter values in a column.
I notice you can set a filter in a Dataset or the tablix. The problem is I do not have something a function that do both LIKE and IN
Do you someone have an idea?
I tried already the LIKE function and the VALUE =”*”+”Parameters!PAR.Value”+”*”.
It did work, but not on a multiple values parameter.
I don't think you will be able to do this using dataset filters using a multi-value parameter.
However, you should be able to change your dataset query to handle this.
CREATE PROC myProc (#myParameter varchar(1000))
AS
SELECT * FROM myTable t
JOIN string_split(#myParameter, ',') p on t.myColumn like '%' + p.value + '%'
When you pass the parameter to the stored proc you can use the following expression
=JOIN(Parameters!myParameter.Value, ",")
This will simply join each of your parameter values into a single comma separated string string ready to pass to the procedure.
If you do not have a version of SQL Server that support string_split
Hers's the code to create one. There are smaller versions around on the internet but this one was designed to handle special cases as well as the typical single character delimiters.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [Split](#sText varchar(8000), #sDelim varchar(20) = ' ')
RETURNS #retArray TABLE (idx smallint Primary Key, value varchar(8000))
AS
BEGIN
DECLARE #idx smallint,
#value varchar(8000),
#bcontinue bit,
#iStrike smallint,
#iDelimlength tinyint
IF #sDelim = 'Space'
BEGIN
SET #sDelim = ' '
END
SET #idx = 0
SET #sText = LTrim(RTrim(#sText))
SET #iDelimlength = DATALENGTH(#sDelim)
SET #bcontinue = 1
IF NOT ((#iDelimlength = 0) or (#sDelim = 'Empty'))
BEGIN
WHILE #bcontinue = 1
BEGIN
--If you can find the delimiter in the text, retrieve the first element and
--insert it with its index into the return table.
IF CHARINDEX(#sDelim, #sText)>0
BEGIN
SET #value = SUBSTRING(#sText,1, CHARINDEX(#sDelim,#sText)-1)
BEGIN
INSERT #retArray (idx, value)
VALUES (#idx, #value)
END
--Trim the element and its delimiter from the front of the string.
--Increment the index and loop.
SET #iStrike = DATALENGTH(#value) + #iDelimlength
SET #idx = #idx + 1
SET #sText = LTrim(Right(#sText,DATALENGTH(#sText) - #iStrike))
END
ELSE
BEGIN
--If you can't find the delimiter in the text, #sText is the last value in
--#retArray.
SET #value = #sText
BEGIN
INSERT #retArray (idx, value)
VALUES (#idx, #value)
END
--Exit the WHILE loop.
SET #bcontinue = 0
END
END
END
ELSE
BEGIN
WHILE #bcontinue=1
BEGIN
--If the delimiter is an empty string, check for remaining text
--instead of a delimiter. Insert the first character into the
--retArray table. Trim the character from the front of the string.
--Increment the index and loop.
IF DATALENGTH(#sText)>1
BEGIN
SET #value = SUBSTRING(#sText,1,1)
BEGIN
INSERT #retArray (idx, value)
VALUES (#idx, #value)
END
SET #idx = #idx+1
SET #sText = SUBSTRING(#sText,2,DATALENGTH(#sText)-1)
END
ELSE
BEGIN
--One character remains.
--Insert the character, and exit the WHILE loop.
INSERT #retArray (idx, value)
VALUES (#idx, #sText)
SET #bcontinue = 0
END
END
END
RETURN
END
GO
To test this try something like
select * from Split('abc,def,ghi', ',')
which will return
when I do:
SELECT *
FROM SOMETABLE
I get all the columns from SOMETABLE, but I DON'T want the columns which are NULL (for all records). How do I do this?
Reason: this table has 20 columns, 10 of these are set but 10 of them are null for certain queries. And it is time consuming to type the columnnames....
Thanks,
Voodoo
SQL supports the * wildcard which means all columns. There is no wildcard for all columns except the ones you don't want.
Type out the column names. It can't be more work than asking questions on Stack Overflow. Also, copy & paste is your friend.
Another suggestion is to define a view that selects the columns you want, and then subsequently you can select * from the view any time you want.
It's possible to do, but kind of complicated. You can retrieve the list of columns in a table from INFORMATION_SCHEMA.COLUMNS. For each column, you can run a query to see if any non-null row exists. Finally, you can run a query based on the resulting column list.
Here's one way to do that, with a cursor:
declare #table_name varchar(256)
set #table_name = 'Airports'
declare #rc int
declare #query nvarchar(max)
declare #column_list varchar(256)
declare columns cursor local for select column_name
from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = #table_name
open columns
declare #column_name varchar(256)
fetch next from columns into #column_name
while ##FETCH_STATUS = 0
begin
set #query = 'select #rc = count(*) from ' + #table_name + ' where ' +
#column_name + ' is not null'
exec sp_executesql #query = #query, #params = N'#rc int output',
#rc = #rc output
if #rc > 0
set #column_list = case when #column_list is null then '' else
#column_list + ', ' end + #column_name
fetch next from columns into #column_name
end
close columns
deallocate columns
set #query = 'select ' + #column_list + ' from ' + #table_name
exec sp_executesql #query = #query
This runs on SQL Server. It might be close enough for Sybase. Hopefully, this demonstrates that typing out a column list isn't that bad :-)
I am a little stuck... I am trying to take the output from a query and break it into numerous files based on a single criteria. I am getting an error of converting a varchar type to int and I cannot figure out why. Working in SQL Server 2008...
DECLARE #LOOP AS INT;
DECLARE #SQL AS VARCHAR(MAX);
DECLARE #BCP AS VARCHAR(MAX);
DECLARE #COUNTER AS INT;
DECLARE #FILENAME AS VARCHAR(MAX);
SET #COUNTER='1'
SELECT #LOOP = COUNT(DISTINCT LIST_ID) FROM DATA_TABLE
WHERE STATUS='2' AND LIST_ID IS NOT NULL ;
SET #SQL=(SELECT CUSTOMER_NO FROM CUSTOMER A, DATA_TABLE B
WHERE A.CUSTOMER_ID=B.CUSTOMER_ID AND A.STATUS='2' AND LIST_ID='+#LOOP+');
SET #FILENAME='QUERYOUT C:\Projects\FILE_"'+#LOOP+'.TXT'
WHILE #COUNTER<=#LOOP
BEGIN
SELECT
#BCP='BCP "'+#SQL+'+'+#FILENAME+''
SET #COUNTER=#COUNTER+1
END
GO
The error I am getting is:
Msg 245, Level 16, State 1, Line 10
Conversion failed when converting the varchar value '+#LOOP+' to data type int.
I am trying to use the LOOP value to let me know the contents of each file. For example, LOOP='1' would mean the file contains the customer records associate with LIST_ID='1'
Thoughts on the error?
I'm not sure I understand exactly what you need but if you want to issue the BCP command for every LIST_ID you need to loop though them and execute for each one.
This may not be what you need but rather than wait until I am home from work I will post it now.
DECLARE #FILENAME AS VARCHAR(MAX);
DECLARE #LISTID INT
DECLARE #LOOP AS INT;
DECLARE #BCP AS VARCHAR(MAX);
DECLARE #SQL AS VARCHAR(MAX);
DECLARE cur CURSOR FOR SELECT DISTINCT LIST_ID FROM DATA_TABLE WHERE STATUS='2' AND LIST_ID IS NOT NULL
OPEN cur
FETCH NEXT FROM cur INTO #LISTID
WHILE ##FETCH_STATUS = 0 BEGIN
SET #FILENAME='QUERYOUT C:\Projects\FILE_'+Cast(#LISTID AS Varchar)+'.TXT -c -t -T'
SET #SQL='(SELECT CUSTOMER_NO FROM CUSTOMER A, DATA_TABLE B WHERE A.CUSTOMER_ID=B.CUSTOMER_ID AND A.STATUS=''2'' AND LIST_ID='+#LISTID+')';
SELECT #BCP='BCP '+#SQL+' '+#FILENAME+''
EXEC xp_cmdshell #BCP
FETCH NEXT FROM cur INTO #LISTID
END
CLOSE cur
DEALLOCATE cur
1.change varchar(max) to varchar(8000)
2.Add DBNAME.SCHEMA for all the tables, because by default it will point to the Master db.
Added double quotes(") below
3. #FILENAME='QUERYOUT "C:\Projects\FILE_'+Cast(#LISTID AS Varchar)+'.TXT" -c -t -T'
4. '("SELECT CUSTOMER_NO FROM CUSTOMER A, DATA_TABLE B WHERE A.CUSTOMER_ID=B.CUSTOMER_ID AND A.STATUS=''2'' AND LIST_ID='+#LISTID+'")';
I have a long string.I want to check throughout this string for consecutive 15 letters if there is no space i have to manually put a space in sql server. Can any one pls help??
For eg. my string is 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ'
then it should appear like 'ABCDEFGHIJKLMNOP QRSTUVWXYZABCDE FGHIJKLMNOPQRST UVWXYZ'
#dcp1986: I tried with your function as below.
SELECT dbo.UF_StringSplitter('HeloEveryonehru Howslyfgoingonn HaveaGoodDayGoodMorning')
But an unexpected split occured. I think your function must be modified as below for the correct result:
IF EXISTS(SELECT * FROM sysobjects WHERE ID = OBJECT_ID('UF_StringSplitter'))
DROP FUNCTION UF_StringSplitter
GO
CREATE FUNCTION UF_StringSplitter (
#psCSString VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #sTemp VARCHAR(MAX)
DECLARE #tTemp VARCHAR(MAX)
SET #tTemp=''
WHILE LEN(#psCSString)>15
BEGIN
SET #sTemp = LEFT(LTRIM(#psCSString), 15)
SET #psCSString = LTRIM(SUBSTRING(#psCSString,16, LEN(#psCSString)))
IF #psCSString LIKE ' %'
SET #tTemp=#tTemp+#sTemp
ELSE
SET #tTemp=#tTemp+#sTemp+' '
END
SET #tTemp=#tTemp+#psCSString
RETURN #tTemp
END
You could use a function like this
IF EXISTS(SELECT * FROM sysobjects WHERE ID = OBJECT_ID('UF_StringSplitter'))
DROP FUNCTION UF_StringSplitter
GO
CREATE FUNCTION UF_StringSplitter
(
#psCSString VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #sTemp VARCHAR(MAX)
DECLARE #tTemp VARCHAR(MAX)
SET #tTemp=''
WHILE LEN(#psCSString)>15
BEGIN
SET #sTemp = LEFT(#psCSString, 15)
SET #psCSString = SUBSTRING(#psCSString,16, LEN(#psCSString))
IF #psCSString LIKE ' %'
SET #tTemp=#tTemp+#sTemp
ELSE
SET #tTemp=#tTemp+#sTemp+' '
END
SET #tTemp=#tTemp+#psCSString
RETURN #tTemp
END
Go
Here i have hard coded the splitting value, and you can use the function
UPDATE mytable SET mycol=dbo.UF_StringSplitter(mycol)
I don't know how to do it on a single statement, but you can create a sql function something like this
create function AddStuffCharacterInLength (#original nvarchar(100), #take int, #stuff varchar(100))
returns nvarchar(200)
AS
BEGIN
declare #result nvarchar(200)
declare #len int
declare #skip int
set #len = len(#original)
set #result = ''
set #skip = (#take * -1) + 1
while #len > 0
begin
set #result = #result + substring(#original, #skip + #take, #take)
set #len = #len - #take
set #skip = #skip + #take
if #len > 0
set #result = #result + ' '
end
RETURN #result
END
And use it like this
select dbo.AddStuffCharacterInLength ('ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ',15, ' ')
And the output should be
----------------------------------------------------------------------------------------------------
ABCDEFGHIJKLMNO PQRSTUVWXYZABCD EFGHIJKLMNOPQRS TUVWXYZ
(1 row(s) affected)
I have the following stored procedure that is meant to implement Dijkstra's shortest path algorithm:
CREATE PROCEDURE `Dijkstras`(IN `pids` VARCHAR(512), IN `startP` VARCHAR(8), IN `endP` VARCHAR(8), OUT `dist` DECIMAL(20,10), OUT `eset` VARCHAR(1024))
BEGIN
DECLARE currentP VARCHAR(4);
DECLARE finished INT DEFAULT 0;
DECLARE pt_from, pt_to int;
DECLARE pt_dist decimal(20,10);
DECLARE done INT DEFAULT 0;
DECLARE cur2 CURSOR FOR
select F.id as `from`, T.id as `to`, dist(F.lat, F.lng, T.lat, T.lng)
as dist
from sampledata F, sampledata T
where F.id < T.id and
find_in_set(convert(F.id, char(10)), pids) and
find_in_set(convert(T.id, char(10)), pids)
order by dist;
DECLARE CONTINUE HANDLER FOR not found SET done = 1;
SET currentP= startP;
SET eset = '';
SET dist = 0;
SET done=0;
OPEN cur2; -- this finds pariwise distances in miles.
REPEAT
FETCH cur2 INTO pt_from, pt_to, pt_dist;
SET dist= dist+pt_dist;
SET eset= CONCAT(eset, ',');
IF(currentP=pt_from OR currentP=pt_to) AND
(IN_SET(pt_from,pids) AND IN_SET(pt_to,pids)) THEN
BEGIN
SET dist= dist+ pt_dist;
SET pids= REMOVE_MEMBER(currentP, pids);
SET eset = concat(eset, ',', concat(pt_from, ':', pt_to));
IF left(eset, 1) = ',' then
SET eset = substring(eset, 2); -- remove extra comma.
END IF;
IF currentP=pt_from THEN
SET currentP=pt_to;
ELSE
SET currentP=pt_from;
END IF;
IF currentP= endP THEN
SET finished= 1;
END IF;
END;
END IF;
UNTIL done
END REPEAT;
CLOSE cur2;
END
My issue is that the cursor isn't working properly. When I fetch the current row into pt_from, pt_to, and pt_dist all I get are NULL values. The sampledata table is properly stored in the database and all the point ids in pids are also in the sampledata table. Plus this EXACT code works for another procedure, but reusing it here isn't working.
Anybody know what I'm doing wrong?
The error was that I passed in the point ids like this '12, 15, 18' with spaces in between. MySQL counts the whitespace when it parses the strings, and the id's in the table were listed without spaces. The correct way to pass in the string set is '12,15,18'.