Eliminate Null Query results from a user defined function - sql

I have the following user defined function that runs correctly; however, it shows all records that return 0 when checked against the ISDATE condition. These records are displayed as NULL values in the query results. I don't want to see those records. How can I remove them from the query results?
I had to setup the ISDATE() check because some log entries have the following format:
("Due Date: -> xx/xx/xxxx" instead of "Due Date: xx/xx/xxxx -> yy/yy/yyyy")
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION ParseValueFromChgLog
(
#LogText varchar(max),
#ValueNum int -- 1 = original date or 2 = changed to date
)
RETURNS date
AS
BEGIN
-- Declare the return variable here
DECLARE #Result date
DECLARE #ValueCheck char(1)
DECLARE #Index bigint
DECLARE #OrigStep bigint
DECLARE #StrDate varchar(max)
-- Parse "Original Date"
IF #ValueNum = 1
BEGIN
SET #Index = 10
SET #OrigStep = 8
SET #StrDate = SUBSTRING(#LogText,CHARINDEX('Due Date', #LogText)+ #Index, #OrigStep)
IF ISDATE(#StrDate) = 1
BEGIN
SET #Result = CAST(SUBSTRING(#LogText,CHARINDEX('Due Date', #LogText)+ #Index, #OrigStep)AS DATE)
--SET #Result = #Date
END
END
-- Parse "Changed to Date"
IF #ValueNum = 2
BEGIN
SET #Index = 21
SET #OrigStep = 9
SET #StrDate = SUBSTRING(#LogText,CHARINDEX('Due Date', #LogText)+ #Index, #OrigStep)
IF ISDATE(#StrDate) = 1
BEGIN
SET #Result = CAST(SUBSTRING(#LogText,CHARINDEX('Due Date', #LogText)+ #Index, #OrigStep)AS DATE)
--SET #Result = #Date
END
END
-- Return the result of the function
RETURN #Result
END
GO
Thanks

There is no way out of returning a value by this function.
But you can filter your query by Where function_Column is not null

Related

Function error for Upper Case and Lower Case

I have a function in SQL Server (version 2008) which converts a column data to Proper Case (make first letter of a string to upper case and rest to lower). The function works fine, however, there is a need for me to use upper case for data appearing as 'Rto.' There are several records in my table that has for example: 'Rto Dist Inc-Brantford', 'Rto Dist Inc-Orillia' and so on. Originally, the data was all upper case but since I used the function to convert all upper case to Proper case, 'RTO..' has also been converted to Proper Case. I would like to keep Rto in all upper case like this: RTO.
I have included my function below with the last part converting the Rto to RTO but this is where I am getting error message from SQL Server that says:
Msg 102, Level 15, State 1, Procedure ProperCase, Line 29
Incorrect syntax near '#Ret'.
My function:
GO
/****** Object: UserDefinedFunction [dbo].[ProperCase] Script Date: 2022-11-30 9:38:28 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER function [dbo].[ProperCase](#Text as varchar(8000))
returns varchar(8000)
as
begin
declare #Reset bit;
declare #Ret varchar(8000);
declare #i int;
declare #c char(1);
if #Text is null
return null;
select #Reset = 1, #i = 1, #Ret = '';
while (#i <= len(#Text))
select #c = substring(#Text, #i, 1),
#Ret = #Ret + case when #Reset = 1 then UPPER(#c) else LOWER(#c) end,
#Reset = case when #c like '[a-zA-Z]' then 0 else 1 end,
#i = #i + 1
**if LEFT(#Ret, 3) = 'Rto'
#Ret = UPPER(#Text);**
return #Ret
end
The block of code in bold:
if LEFT(#Ret, 3) = 'Rto'
#Ret = UPPER(#Text);
was added by me to convert all data appearing as 'Rto.....' to RTO.....
Any guidance to make this code work properly is greatly appreciated
Thank you
I understand why you are using the while loop. It looks like you're trying to make the first character of each word into upper case. I would just add an IF to change the loop variables before entering the while loop. Something like this:
ALTER function [dbo].[ProperCase](#Text as varchar(8000))
returns varchar(8000)
as
begin
declare #Reset bit;
declare #Ret varchar(8000);
declare #i int;
declare #c char(1);
if #Text is null
return null;
select #Reset = 1, #i = 1, #Ret = '';
--Special handling for strings starting with "RTO".
if LEFT(#Text,3) = 'rto'
select #Reset = 1, #i = 4, #Ret = UPPER(LEFT(#Text,3));
while (#i <= len(#Text))
select #c = substring(#Text, #i, 1),
#Ret = #Ret + case when #Reset = 1 then UPPER(#c) else LOWER(#c) end,
#Reset = case when #c like '[a-zA-Z]' then 0 else 1 end,
#i = #i + 1
return #Ret
end

Cursorfetch :The number of variables must match that of selected columns

I have checked over this several times. The column count matches but it still getting an error belows :
Cursorfetch: The number of variables declared in the INTO list must
match that of selected columns.
I know this question has been asked many times, but I still get stuck. Any help will be appreciated. Thanks.
DECLARE #prev_s_Case CHAR(4)= null,#prev_startDate DATETIME= null,#prev_endDate DATETIME= null, #prev_ukey INT= null, #cur_s_Case CHAR(4), #cur_startDate DATETIME, #cur_endDate DATETIME, #cur_ukey INT, #result varchar(500);
DECLARE THE_CURSOR CURSOR FOR
SELECT s_Case, startDate, endDate, ukey FROM #TEMP
ORDER BY s_Case
BEGIN
OPEN THE_CURSOR;
FETCH NEXT FROM THE_CURSOR
INTO #cur_s_Case, #cur_startDate, #cur_endDate, #cur_ukey
WHILE (##FETCH_STATUS=0)
SELECT s_Case, startDate, endDate, ukey
FROM #TEMP
IF ( (#prev_s_Case = #cur_s_Case))
BEGIN
IF ((#cur_startDate BETWEEN #prev_startDate AND #prev_endDate) AND (#cur_endDate >= #prev_endDate))
BEGIN
SET #result = CASE WHEN #result = '' THEN str(#prev_ukey)
ELSE #result + ','+ str(#prev_ukey) END
END
ELSE IF ((#cur_startDate BETWEEN #prev_startDate AND #prev_endDate)
AND (#cur_endDate < #prev_endDate))
BEGIN
SET #result = CASE WHEN #result = '' THEN str(#cur_ukey)
ELSE #result + ','+ str(#cur_ukey) END
END
END
SET #prev_s_Case= #cur_s_Case;
SET #prev_startDate = #cur_startDate;
SET #prev_endDate = #cur_endDate;
SET #prev_ukey = #cur_ukey;
FETCH NEXT FROM THE_CURSOR
INTO #cur_s_Case,#cur_startDate,#cur_endDate,#cur_ukey
print #result
CLOSE THE_CURSOR;
DEALLOCATE THE_CURSOR;
END

The best method to update every row in SQL Server

I have code like this to create random table: (http://dba.fyicenter.com/faq/sql_server/Creating_a_Large_Table_with_Random_Data_for_Indexes.html)
-- Create a table with primary key
CREATE TABLE fyi_random
(
id INT,
rand_integer INT,
rand_number numeric(18,9),
rand_datetime DATETIME,
rand_string VARCHAR(80)
);
-- Insert rows with random values
DECLARE #row INT;
DECLARE #string VARCHAR(80), #length INT, #code INT;
SET #row = 0;
WHILE #row < 100000
BEGIN
SET #row = #row + 1;
-- Build the random string
SET #length = ROUND(80*RAND(),0);
SET #string = '';
WHILE #length > 0
BEGIN
SET #length = #length - 1;
SET #code = ROUND(32*RAND(),0) - 6;
IF #code BETWEEN 1 AND 26
SET #string = #string + CHAR(ASCII('a')+#code-1);
ELSE
SET #string = #string + ' ';
END
-- Ready for the record
SET NOCOUNT ON;
INSERT INTO fyi_random
VALUES (#row,
ROUND(2000000*RAND()-1000000,0),
ROUND(2000000*RAND()-1000000,9),
CONVERT(DATETIME, ROUND(60000*RAND() - 30000, 9) ),
#string)
END
PRINT 'Rows inserted: '+CONVERT(VARCHAR(20),#row);
GO
I want to update every row (for example update column rand_string with some new random string). What is the best method? When I'm trying to do this by while loop performance decreases with increasing rows:
...
SET NOCOUNT ON;
UPDATE random_data
SET rand_string = #string
WHERE id = #row;
I also tried to use cursor statement and it's better but why while loop is so slow? And is there another way to do this better?
If you want to update every row in a table then just omit the where clause in the update statement.

SQL Server, horizontal concatenate Range of Dates

I would like to know the way I could concatenate between two dates in a calculated column horizontally, for example:
date_ini,date_end,result
2016-04-01,2016-04-05,2016-04-01|2016-04-02|2016-04-03|2016-04-04|2016-04-05
2016-04-03,2016-04-06,2016-04-03|2016-04-04|2016-04-05|2016-04-06
2016-04-05,2016-04-05,2016-04-05
2016-04-05,2016-04-06,2016-04-05|2016-04-06
The result is the column I would like to create
Thanks,
A function like this could do the trick. Please change the size of the return varchar to fit your needs.
CREATE FUNCTION dbo.date_concatenate(#start_date DATETIME, #end_date DATETIME)
RETURNS VARCHAR(255)
AS
BEGIN
DECLARE #result VARCHAR(255);
SET #result = '';
IF(#end_date < #start_date)
SET #result = 'Error: End Date can not be less than start date';
ELSE
BEGIN
WHILE (#start_date < #end_date)
BEGIN
SET #result = #result + CONVERT(varchar(10),#start_date,120) + '|'
SET #start_date = DATEADD(dd,1,#start_date)
END
END
SET #result = #result + CONVERT(varchar(10),#end_date,120)
RETURN #result
END

remove numeric values in data using sql

my data is :
Id Case ID#
1. QCCR1A105369, QCCR1A104986 ,QCCR1A103717
2. QCIM1A106902,4613410733 QCIM1A106902; 4613344523 QCIM1A105842; 4614004212 QCIM1A106580; 4614060189 QCIM1A106676
3. QCCR1D93616, QCCR1D92488, QCCR1D58461
4. QCCR1B40216 .... ,QCCR1B39080, QCCR1B40216, QCCR1B39745, QCCR1B38463 , QCCR1B38618, QCCR1B38619, QCCR1B38620, QCCR1B38621, QCCR1B38622, QCCR1B38465, QCCR1B38623
5. QCCR2A30221 QCCR2A30223 QCCR2A30222 QCIM2A30416
My output will be Id 1,3,4,5. I want only that rows, which have starting value QC not any numeric value. For ID 2 you can see there are some numeric values, please tell me how can I achieve it.
You could use a table valued function to split your value by a delimiter like this:
CREATE FUNCTION [dbo].[Split]
(
#ItemList NVARCHAR(MAX),
#delimiter CHAR(1)
)
RETURNS #ItemTable TABLE (Item VARCHAR(250))
AS
BEGIN
DECLARE #tempItemList NVARCHAR(MAX)
SET #tempItemList = #ItemList
DECLARE #i INT
DECLARE #Item NVARCHAR(4000)
SET #i = CHARINDEX(#delimiter, #tempItemList)
WHILE (LEN(#tempItemList) > 0)
BEGIN
IF #i = 0
SET #Item = #tempItemList
ELSE
SET #Item = LEFT(#tempItemList, #i - 1)
INSERT INTO #ItemTable(Item) VALUES(#Item)
IF #i = 0
SET #tempItemList = ''
ELSE
SET #tempItemList = RIGHT(#tempItemList, LEN(#tempItemList) - #i)
SET #i = CHARINDEX(#delimiter, #tempItemList)
END
RETURN
END
Then this query returns the expected result:
SELECT t.*
FROM dbo.TableName t
WHERE NOT EXISTS
(
SELECT 1 FROM dbo.Split(t.CaseID, ',') split
WHERE NOT LEFT(LTRIM(split.Item), 2) = 'QC'
OR ISNUMERIC(split.Item) = 1
)
Demo with your sample data. But in general you should avoid multiple values in one column. Instead store it in separate rows in a linked table. That's called database normalization.