Duration = isnull(FunctionA(DateA,DateB),'')
The Function above calculates number of days and if day is null it displays
the value 0 instead of blank value
How can I change the above code to so that it shows blank and not 0 for value null?
If your function returns an integer the result from isnull will also be an integer. In the case the return value is null you will have an implicit conversion to integer for '' and that will be 0.
Try this:
declare #xx int
select isnull(#xx,'')
Result:
-----------
0
You can have the space if you first cast the return value from your function to varchar.
declare #xx int
select isnull(cast(#xx as varchar(10)),'')
Result:
----------
.
If your function returns 0 instead of null you can use nullif to get a null value before you cast to varchar.
declare #xx int = 0
select isnull(cast(nullif(#xx, 0) as varchar(10)),'')
Summary:
You need this:
Duration = isnull(cast(FunctionA(DateA,DateB) as varchar(10)),'')
or this
Duration = isnull(cast(nullif(FunctionA(DateA,DateB), 0) as varchar(10)),'')
If Duration is datatype int then you can't change that to an empty string (blank). You'll either have to change that to a string datatype (varchar for instance) or be okay with 0. int can either be NULL (if it is allowed) or a valid integer value. A blank string is not a valid integer value.
I use case statements and casting to do this.
Example:
case when columnX <> 0 then cast(columnX as nvarchar) else '' end
Basically, you're changing your numeric to show either as a character or a blank. You will have to do all your math before you change to nvarchar though, because outside of this, it becomes a string. It would be helpful if BLANK was a command and worked with numeric values though.
Hope this helps someone.
Is FunctionA returning 0 instead of null? The code you've written may be ok, but if FunctionA never returns null then...
You could declare Duration as a sql_variant datatype and allow implicit conversion to occur
so something like this should work
declare #DURATION sql_variant
select COALESCE(#DURATION, '')
set #DURATION=1
select COALESCE(#DURATION, '')
Related
Well it would rather be a very simple thing but I couldn't figure out myself.
While trying the below line in Stored Procedure in MYSQL server, it converts or sets the column datatype to BIGINT instead of expected INT
CASE `L`.`Code` WHEN 'ABCD' THEN 0 ELSE `XL`.`ID` END as XLID
The magical thing is that if I remove the 0 from it, then it returns INT as datatype as expected. So this 0 is to blame for sure, but I couldn't understand why and how to resolve this? I tried to use CAST but it didn't allow to cast INT to INT.
Would be a great help.
The following trick can help:
DELIMITER //
CREATE FUNCTION `return_integer`(`number` INT UNSIGNED)
RETURNS INT UNSIGNED DETERMINISTIC
BEGIN
RETURN `number`;
END//
DELIMITER ;
SELECT
CASE `L`.`Code`
WHEN 'ABCD' THEN `return_integer`(0)
ELSE `L`.`ID`
END AS XLID
FROM `table_name` `L`;
My function is has two variables ('date', number of months to subtract from 'date').
here is my function:
create function a_testbed.PrevMonth (
in_date date,
in_mn_count int)
RETURNS int
BEGIN
/* local variable declaration */
declare v_date int(255);
declare v_date_format varchar(10);
declare v_date_sub varchar(10);
set v_date_format := DATE_FORMAT(v_date, '%Y-%m');
set v_date_sub := DATE_FORMAT(curdate(), '%Y-%m');
if (in_date is null) then
set v_date := v_date_sub;
elseif (in_mn_count is null or in_mn_count < 0) then
set in_mn_count := 0;
else
set v_date := v_date_sub;
end if;
RETURN v_date_format;
END;
#
Keep getting the error:
ERROR 1265 (01000) Data Truncated for column 'v_date' at row 1
any thoughts?
thanks!
There are lots of things wrong with your function:
You do set v_date_format := DATE_FORMAT(v_date, '%Y-%m');, but this is before you assignea value to v_date.
Later you assign set v_date := v_date_sub;, but you never use v_date after that, so what is the point?
You assign set in_mn_count := 0;, but never use this variable, either.
Finally you do RETURN v_date_format;. v_date_format is a VARCHAR, but the function is declared to return INT. And the contents of this string is in the form YYYY-MM, so it doesn't look like an integer.
I'm not sure if any of these are causing the Data truncated error, but that hardly seems to be important when the function is so broken.
You assign varchar to int set v_date := v_date_sub;
Change this:
declare v_date varchar(10);
I don't believe "INT(255)" is a valid datatype.
I know the 255 is just a display width attribute. The INT datatype defines the range of values, the display width doesn't impact the range of values. But I've just never seen the length modifier on an INT larger than 11. (10 for an unsigned int) (?)
As a test, you could try specifying INT(11), or just INT.
More problematic, perhaps, is that this variable with datatype INT is being passed as the first argument to DATE_FORMAT function. But the first argument of DATE_FORMAT needs to be a DATE, DATETIME or TIMESTAMP (iirc). There may be some implicit conversion from INT to DATE, but I don't think there is.
I don't understand why you need a function to subtract a number of months from a DATE. MySQL has builtin in functions, and simple expressions that do that.
For example:
dateexpr + INTERVAL -6 MONTH
returns a DATE (or DATETIME) value with 6 months subtracted from dateexpr.
If you need to "round down" to the first of the month, or convert to a string with just the 'yyyy-mm', you can do a DATE_FORMAT(dateexpr,'%Y-%m-01') or a SUBSTRING(dateexpr,1,7), respectively.
review
CREATE FUNCTION a_testbed.PrevMonth (
in_date date,
in_mn_count int)
That looks okay, two input parameters, a DATE and an INT. (Function parameters are always IN parameters.)
RETURNS int
A bit odd that a function named PrevMonth takes a DATE argument, but returns an INT, rather than a DATE, but this isn't an error.
BEGIN
/* local variable declaration */
DECLARE v_date INT(255);
The display width of 255 is bizzarre. Never seen that on an INT before.
DECLARE v_date_format VARCHAR(10);
DECLARE v_date_sub VARCHAR(10);
Two strings, looks fine.
SET v_date_format := DATE_FORMAT(v_date, '%Y-%m');
^^^^^^
But v_date is an INT, not a DATE or DATETIME. And it's not initialized, so it's NULL. If this doesn't throw an exception, then we'd expect v_date_format to be NULL. (I suspect you wanted to specify in_date here in place of v_date.)
SET v_date_sub := DATE_FORMAT(curdate(), '%Y-%m');
This should get us 7 characters, e.g. '2013-07'. So no problem there.
IF (in_date IS NULL) THEN
SET v_date := v_date_sub;
Here's a usage of the in_date parameter. Check if it's null. If it is, assign the same 7 characters that we assigned to v_date_sub. Got it.
ELSEIF (in_mn_count IS NULL OR in_mn_count < 0) THEN
SET in_mn_count := 0;
Is it valid to assign a value to an IN parameter? (That may be valid, but it is odd. Normally we don't assign values to parameters unless they are OUT, or INOUT paremeters. We normally assign values to procedure variables (and sometimes MySQL user variables.)
Why is this dependent on whether in_date is null or not (the preceding IF). Seems like we would want to check this parameter in either case.
ELSE
SET v_date := v_date_sub;
Isn't this the same action specified under the first IF? It seems like the logic here reads "if in_date is not null and ifnull(in_mn_count,-1)<0" we do one thing, else we do somthing else. We're either trying to assign a value to an IN parameter, or we're assigning current YYYY-MM to v_date.
END IF;
So far, the only use of the in_date parameter has been to check if it is NULL. And the only usage of the in_mn_count parameter has been to try to assign a zero to it, if it's null or less than zero.
RETURN v_date_format;
The only time we assigned anything to v_date_format was at the beginning of the function, when we assigned the return from a DATE_FORMAT function, passing in a NULL value (as an INT rather than a DATE.) So what was all the other code supposed to be doing?
END
Yes, please, end. There is so much wrong in this function, it makes my head hurt. So, please, yes, END. Just make it stop.
I have a strange bug that I cannot resolve (with a one line function).
This code works:
DECLARE #TestDate datetime = '2013-05-01 23:15:11'
select IsNull(convert(varchar(max), #TestDate, 120), 'null') as 'test1'
Displays: 2013-05-01 23:15:11
CREATE FUNCTION [dbo].[DateOrNullToChar] (#InputDate date)
RETURNS VARCHAR(40)
BEGIN
return ISNULL(convert(varchar(40),#InputDate, 120),'null');
END
select dbo.DateOrNullToChar('2013-05-01 23:15:11') as 'result'
Returns: 2013-05-01 (no time)
I have also tried varchar(max).
The purpose of the function is for something like this:
Set #ErrorMessage = ' #ArrivalDate=' + dbo.DateOrNullToChar(#ArrivalDate) +
' #DepartureDate=' + dbo.DateOrNullToChar(#DepartureDate);
If any one value is null, the whole value becomes null. So I want to see the string 'null' when a date has a null value.
#InputDate should be datetime or datetime2 if you want time to be shown
The clues are in the code...
#TestDate datetime
#InputDate date
You need to make the parameter type to be datetime instead of date:
CREATE FUNCTION [dbo].[DateOrNullToChar] (#InputDate datetime)
It's silently converting the string to your date parameter type and thus dropping the time portion.
I am exporting a SELECT result to CSV via INTO OUTFILE. I have a series of simple SQL string functions I use to format the data. For instance: CONCAT('$',FORMAT(property.price,2)). I would like to otherwise return an empty string if the value is NULL, but I am unsure how to do both at the same time.
Also I am wondering the easiest way to take a TinyInt value of 0 or 1 and return "yes" or "no".
For tinyint you can use IF operator
select if(tinyint_value,'yes','no')
for first part you also can use if operator
select if(property.price is not null, CONCAT('$',FORMAT(property.price,2)),'')
To return yes, no or empty string depending on he value of the column you can use case as so:
select case column when 1 then 'Yes' else 'No' end as columalias ,
case when stringcolumn is NULL then '' else stringcolumn end as stringcolumn
from table
or
select case column when 1 then 'Yes' else 'No' end as columalias ,
IFNULL(stringcolumn,'') as stringcolumn
from table
You can use the coalesce() function. It returns the first of its arguments that's not NULL.
SELECT COALESCE(NULL, 1);
-> 1
SELECT COALESCE(2, 1);
-> 2
With the following example stored procedure
DECLARE Variable DOUBLE;
DECLARE Variable2 DOUBLE;
SELECT Something FROM Somewhere INTO Variable;
SELECT Something FROM SomewhereElse INTO Variable 2;
SELECT (Variable + Variable2);
If either Variable or Variable2 are NULL then the final SELECT will return null, what I would like is that if they are null they should be converted into 0.00 before the final SELECT, how do you do this? I already tried adding
SELECT 0.00 INTO Variable WHERE Variable IS NULL;
just above the final select but that didn't work.
SELECT COALESCE(variable, 0) + COALESCE(variable2, 0)
if you want each variable null converted to 0 use the solution posted by Quassnoi
SELECT COALESCE(variable, 0) + COALESCE(variable2, 0)
if you want to have 0 if either variable is null then use
SELECT COALESCE(variable + variable2, 0)
Quassnoi's correct, but it's even simpler (and a bit faster) to just coalesce the result:
SELECT coalesce( Variable + Variable2, 0 );
This works because for almost all operators, any null operand will make the operation null:
select 1 + null ; -- null
select null + 1 ; -- null
select null + null ; -- null
In the expression: SELECT coalesce( Variable + Variable2, 0 ); the result of the addition expression Variable + Variable2 is coalesce first argument; if that's null, coalesce returns its second argument, 0, otherwise it returns the (non-null) value of its first argument, which is the sum we want.
The few operators and functions that don't return null for a null operand are those designed to work on nulls: coalesce, is null, is not null.
As kristof notes below, the value of the select expression is different using Quassnoi's expression, if only one variable is null: his will return the value of the non-null variable if one is null; mine will return zero if either variable is null. Which is "right" depends on your intent.